reis-mobile 0.3.6 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +24 -0
- package/README.md +175 -168
- package/THIRD_PARTY_NOTICES.md +224 -4
- package/agents/android-architect.md +89 -0
- package/agents/android-performance-engineer.md +92 -0
- package/agents/android-test-engineer.md +97 -0
- package/agents/flutter-test-engineer.md +2 -0
- package/agents/ios-architect.md +93 -0
- package/agents/ios-performance-engineer.md +92 -0
- package/agents/ios-test-engineer.md +95 -0
- package/agents/lead-mobile.md +10 -1
- package/agents/mobile-staff-engineer.md +1 -1
- package/agents/rn-architect.md +94 -0
- package/agents/rn-performance-engineer.md +92 -0
- package/agents/rn-test-engineer.md +98 -0
- package/bin/reis-mobile.mjs +59 -17
- package/commands/debate.md +10 -1
- package/commands/debug.md +60 -0
- package/commands/reis-mobile.md +7 -2
- package/core/config/project.mjs +59 -0
- package/core/registry/frontmatter.mjs +15 -4
- package/core/registry/registry.mjs +21 -1
- package/core/router/intents.mjs +2 -0
- package/core/router/router.mjs +10 -5
- package/package.json +1 -1
- package/skills/android-adaptive/SKILL.md +304 -0
- package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/flexbox/container-behavior.md +112 -0
- package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/flexbox/get-started.md +69 -0
- package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/flexbox/index.md +81 -0
- package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/flexbox/item-behavior.md +170 -0
- package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/container-properties.md +415 -0
- package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/get-started.md +51 -0
- package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/index.md +73 -0
- package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/item-properties.md +170 -0
- package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/mediaquery/index.md +333 -0
- package/skills/android-adaptive/references/android/develop/ui/compose/tooling/debug.md +114 -0
- package/skills/android-adaptive/references/android/guide/navigation/navigation-3/recipes/material-listdetail.md +141 -0
- package/skills/android-agp-9-upgrade/SKILL.md +106 -0
- package/skills/android-agp-9-upgrade/references/android/build/migrate-to-built-in-kotlin.md +416 -0
- package/skills/android-agp-9-upgrade/references/android/build/releases/agp-9-0-0-release-notes.md +554 -0
- package/skills/android-agp-9-upgrade/references/buildconfig.md +54 -0
- package/skills/android-agp-9-upgrade/references/ksp-kapt.md +39 -0
- package/skills/android-agp-9-upgrade/references/paparazzi-gradle-9.md +30 -0
- package/skills/android-agp-9-upgrade/references/recipes.md +62 -0
- package/skills/android-appfunctions/SKILL.md +74 -0
- package/skills/android-appfunctions/references/adb-interaction-testing.md +95 -0
- package/skills/android-appfunctions/references/context.md +26 -0
- package/skills/android-appfunctions/references/feature-discovery-analysis.md +71 -0
- package/skills/android-appfunctions/references/implementation-configuration.md +282 -0
- package/skills/android-appfunctions/references/kdoc-refinement-optimization.md +75 -0
- package/skills/android-appfunctions/references/migrate-to-service-entry-point.md +226 -0
- package/skills/android-camerax/SKILL.md +135 -0
- package/skills/android-camerax/references/camera1-to-camerax.md +198 -0
- package/skills/android-camerax/references/camera2-to-camerax.md +193 -0
- package/skills/android-camerax/references/expert-blueprints.md +58 -0
- package/skills/android-camerax/references/foldables.md +83 -0
- package/skills/android-camerax/references/immutability.md +60 -0
- package/skills/android-camerax/references/low-light.md +124 -0
- package/skills/android-camerax/references/mlkit-spatial.md +75 -0
- package/skills/android-camerax/references/modern-apis.md +42 -0
- package/skills/android-camerax/references/testing.md +69 -0
- package/skills/android-camerax/references/thermals.md +85 -0
- package/skills/android-camerax/references/wear-os.md +76 -0
- package/skills/android-camerax/references/xr.md +54 -0
- package/skills/android-cli/SKILL.md +474 -0
- package/skills/android-cli/references/interact.md +113 -0
- package/skills/android-cli/references/journeys.md +120 -0
- package/skills/android-code-review/SKILL.md +58 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/SKILL.md +340 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/design/ui/ai-glasses/guides/interaction/inputs.md +67 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/access-hardware-projected-context.md +388 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/buttons.md +139 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/cards.md +148 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/focus.md +107 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/icons.md +90 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/text.md +69 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/title-chips.md +82 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/request-hardware-permissions.md +213 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/button-samples-source.md +176 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/button-source.md +203 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/card-samples-source.md +296 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/card-source.md +515 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/deptheffect-source.md +224 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/deptheffectlevels-source.md +105 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/glimmersansflextypography-source.md +270 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/glimmertheme-source.md +182 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/icon-source.md +388 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/iconbutton-source.md +126 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/iconsizes-source.md +78 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/list-source.md +27 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/listitem-source.md +272 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/liststate-source.md +427 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/material-hct-source.md +217 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/projectedcontext-source.md +265 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/stack-source.md +368 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/stackitemscope-source.md +440 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/stackstate-source.md +325 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/surface-source.md +1211 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/titlechip-samples-source.md +101 -0
- package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/titlechip-source.md +131 -0
- package/skills/android-edge-to-edge/SKILL.md +429 -0
- package/skills/android-engage-sdk-integration/SKILL.md +130 -0
- package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/faq.md +439 -0
- package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/food.md +1149 -0
- package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/healthandfitness.md +1055 -0
- package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/listen.md +1050 -0
- package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/otherverticals.md +1301 -0
- package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/read.md +910 -0
- package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/shopping.md +1224 -0
- package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/social.md +719 -0
- package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/travel.md +1413 -0
- package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/tv/continue-watching/index.md +19 -0
- package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/tv/entitlements.md +353 -0
- package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/tv/getting-started.md +202 -0
- package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/tv/recommendations.md +471 -0
- package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/watch.md +1081 -0
- package/skills/android-engage-sdk-integration/references/clusters.md +154 -0
- package/skills/android-engage-sdk-integration/references/common.md +519 -0
- package/skills/android-engage-sdk-integration/references/patterns.md +527 -0
- package/skills/android-engage-sdk-integration/references/requests.md +260 -0
- package/skills/android-engage-sdk-integration/references/schemas/food.md +509 -0
- package/skills/android-engage-sdk-integration/references/schemas/listen.md +842 -0
- package/skills/android-engage-sdk-integration/references/schemas/other.md +220 -0
- package/skills/android-engage-sdk-integration/references/schemas/read.md +412 -0
- package/skills/android-engage-sdk-integration/references/schemas/shopping.md +357 -0
- package/skills/android-engage-sdk-integration/references/schemas/social.md +228 -0
- package/skills/android-engage-sdk-integration/references/schemas/travel.md +923 -0
- package/skills/android-engage-sdk-integration/references/schemas/tv.md +1226 -0
- package/skills/android-engage-sdk-integration/references/schemas/watch.md +1137 -0
- package/skills/android-engage-sdk-integration/references/troubleshooting.md +39 -0
- package/skills/android-gradle-build-debug/SKILL.md +71 -0
- package/skills/android-intent-security/SKILL.md +550 -0
- package/skills/android-leanback-to-compose-tv-migration/SKILL.md +743 -0
- package/skills/android-leanback-to-compose-tv-migration/references/android/training/tv/get-started/navigation.md +372 -0
- package/skills/android-leanback-to-compose-tv-migration/references/android/training/tv/playback/compose/browse.md +243 -0
- package/skills/android-leanback-to-compose-tv-migration/references/android/training/tv/playback/compose/index.md +153 -0
- package/skills/android-media3-cast-integration/SKILL.md +236 -0
- package/skills/android-media3-cast-integration/references/android/media/media3/cast/create-castplayer.md +390 -0
- package/skills/android-media3-cast-integration/references/android/media/media3/cast/customize-castoptions.md +93 -0
- package/skills/android-media3-cast-integration/references/android/media/media3/cast/index.md +21 -0
- package/skills/android-migrate-xml-views-to-jetpack-compose/SKILL.md +127 -0
- package/skills/android-migrate-xml-views-to-jetpack-compose/references/analysis-of-the-project-and-layout.md +42 -0
- package/skills/android-migrate-xml-views-to-jetpack-compose/references/android/develop/ui/compose/designsystems/migrate-xml-theme-to-compose.md +171 -0
- package/skills/android-migrate-xml-views-to-jetpack-compose/references/android/develop/ui/compose/migrate/interoperability-apis/compose-in-views.md +299 -0
- package/skills/android-migrate-xml-views-to-jetpack-compose/references/android/develop/ui/compose/migrate/interoperability-apis/views-in-compose.md +286 -0
- package/skills/android-migrate-xml-views-to-jetpack-compose/references/android/develop/ui/compose/setup-compose-dependencies-and-compiler.md +197 -0
- package/skills/android-migrate-xml-views-to-jetpack-compose/references/identify-optimal-xml-candidate.md +31 -0
- package/skills/android-migrate-xml-views-to-jetpack-compose/references/xml-layout-migration.md +86 -0
- package/skills/android-ml-kit-genai-prompt-api/SKILL.md +124 -0
- package/skills/android-ml-kit-genai-prompt-api/references/get-started.md +272 -0
- package/skills/android-ml-kit-genai-prompt-api/references/prefix-caching.md +146 -0
- package/skills/android-ml-kit-genai-prompt-api/references/prompt-design.md +55 -0
- package/skills/android-ml-kit-genai-prompt-api/references/prompt-optimization.md +74 -0
- package/skills/android-ml-kit-genai-prompt-api/references/structured-output.md +219 -0
- package/skills/android-ml-kit-genai-prompt-api/references/system-instructions.md +71 -0
- package/skills/android-navigation-3/SKILL.md +122 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/index.md +51 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/migration-guide.md +670 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/animations.md +147 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/basic.md +89 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/basicdsl.md +85 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/basicsaveable.md +90 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/bottomsheet.md +195 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/common-ui.md +200 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/conditional-transitions.md +182 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/conditional.md +230 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/deeplinks-custommatcher.md +176 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/deeplinks-staticuri.md +140 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/deeplinks-syntheticbackstack.md +184 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/dialog.md +107 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/lifecycle-owner.md +185 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/material-listdetail.md +141 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/material-supportingpane.md +145 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/modular-hilt.md +283 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/modular-koin.md +287 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/multiple-backstacks.md +468 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/passingarguments.md +371 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/results-event.md +273 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/results-state.md +266 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/scenes-listdetail.md +435 -0
- package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/scenes-twopane.md +244 -0
- package/skills/android-navigation-3/references/android/guide/navigation/type-safe-destinations.md +129 -0
- package/skills/android-navigation-event/SKILL.md +312 -0
- package/skills/android-navigation-event/references/android/guide/navigation/navigation-event/dispatcher.md +134 -0
- package/skills/android-navigation-event/references/android/guide/navigation/navigation-event/handle-back.md +217 -0
- package/skills/android-navigation-event/references/android/guide/navigation/navigation-event/index.md +83 -0
- package/skills/android-navigation-event/references/android/guide/navigation/navigation-event/setup.md +32 -0
- package/skills/android-play-billing-library-version-upgrade/SKILL.md +96 -0
- package/skills/android-play-billing-library-version-upgrade/references/android/google/play/billing/release-notes.md +1240 -0
- package/skills/android-play-billing-library-version-upgrade/references/migration-logic.md +78 -0
- package/skills/android-play-billing-library-version-upgrade/references/version-checklist.md +54 -0
- package/skills/android-play-policy-insights/SKILL.md +172 -0
- package/skills/android-play-policy-insights/resources/common_mandates.md +100 -0
- package/skills/android-play-policy-insights/resources/compliance_report_template.md +59 -0
- package/skills/android-play-policy-insights/resources/critic.md +86 -0
- package/skills/android-play-policy-insights/resources/goal_data_safety.md +212 -0
- package/skills/android-play-policy-insights/resources/goal_permissions_and_apis.md +459 -0
- package/skills/android-play-policy-insights/resources/goal_user_account.md +106 -0
- package/skills/android-play-policy-insights/resources/policies.json +321 -0
- package/skills/android-play-policy-insights/resources/scanner_config.json +843 -0
- package/skills/android-play-policy-insights/scripts/generate_report.py +860 -0
- package/skills/android-play-policy-insights/scripts/orchestrator.py +1313 -0
- package/skills/android-play-policy-insights/scripts/play_store_scraper.py +410 -0
- package/skills/android-play-policy-insights/scripts/scanner.py +261 -0
- package/skills/android-play-policy-insights/scripts/template_engine.py +243 -0
- package/skills/android-profiler/SKILL.md +60 -0
- package/skills/android-profiler/analysis/analysis_orchestrator.md +32 -0
- package/skills/android-profiler/analysis/workflows/perfetto-sql/perfetto_sql.md +28 -0
- package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/perfetto_trace_analysis.md +121 -0
- package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/guiding_principles.md +51 -0
- package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/domain_hints_template.md +7 -0
- package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_cpu.md +56 -0
- package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_graphics.md +51 -0
- package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_io.md +46 -0
- package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_ipc.md +41 -0
- package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_memory.md +55 -0
- package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_power.md +33 -0
- package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/per_candidate_analysis.md +172 -0
- package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/triage.md +94 -0
- package/skills/android-profiler/recording/recording_orchestrator.md +36 -0
- package/skills/android-profiler/recording/workflows/perfetto-trace-recording/perfetto_trace_recording.md +148 -0
- package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/app_jank.pftxt +43 -0
- package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/cpu_profile.pftxt +35 -0
- package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/java_heap_dump.pftxt +21 -0
- package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/long_background.pftxt +37 -0
- package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/memory_counters.pftxt +45 -0
- package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/native_heap.pftxt +21 -0
- package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/sched_cpu.pftxt +33 -0
- package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/trace_config_reference.md +102 -0
- package/skills/android-profiler/references/env_setup.md +15 -0
- package/skills/android-profiler/references/perfetto/setup.md +29 -0
- package/skills/android-profiler/references/perfetto/sql.md +327 -0
- package/skills/android-r8-analyzer/SKILL.md +72 -0
- package/skills/android-r8-analyzer/references/CONFIGURATION-ANALYZER.md +287 -0
- package/skills/android-r8-analyzer/references/CONFIGURATION.md +44 -0
- package/skills/android-r8-analyzer/references/KEEP-RULES-IMPACT-HIERARCHY.md +83 -0
- package/skills/android-r8-analyzer/references/REDUNDANT-RULES.md +222 -0
- package/skills/android-r8-analyzer/references/REFLECTION-GUIDE.md +139 -0
- package/skills/android-r8-analyzer/references/REPORT_FORMAT.md +51 -0
- package/skills/android-r8-analyzer/references/android/topic/performance/app-optimization/enable-app-optimization.md +252 -0
- package/skills/android-r8-analyzer/references/android/training/testing/other-components/ui-automator.md +312 -0
- package/skills/android-restore-credentials/SKILL.md +359 -0
- package/skills/android-restore-credentials/references/android/guide/topics/manifest/application-element.md +832 -0
- package/skills/android-restore-credentials/references/android/identity/passkeys/create-passkeys.md +327 -0
- package/skills/android-restore-credentials/references/android/identity/passkeys/sign-in-with-passkeys.md +219 -0
- package/skills/android-styles/SKILL.md +229 -0
- package/skills/android-styles/references/android/develop/ui/compose/designsystems/custom.md +459 -0
- package/skills/android-styles/references/android/develop/ui/compose/styles/fundamentals.md +421 -0
- package/skills/android-styles/references/android/develop/ui/compose/styles/state-animations.md +461 -0
- package/skills/android-styles/references/android/develop/ui/compose/styles/styles-vs-modifiers.md +48 -0
- package/skills/android-styles/references/android/develop/ui/compose/styles/theming.md +269 -0
- package/skills/android-verified-email/SKILL.md +432 -0
- package/skills/android-verified-email/references/android/identity/credential-manager/index.md +67 -0
- package/skills/android-verified-email/references/android/identity/digital-credentials/credential-verifier.md +166 -0
- package/skills/android-verified-email/references/android/identity/digital-credentials/email-verification-implementation.md +313 -0
- package/skills/android-verified-email/references/android/identity/digital-credentials/email-verification.md +158 -0
- package/skills/android-verified-email/references/android/identity/digital-credentials/index.md +112 -0
- package/skills/android-verified-email/references/android/identity/passkeys/create-passkeys.md +327 -0
- package/skills/android-verified-email/references/android/identity/sign-in/credential-manager-webview.md +84 -0
- package/skills/android-wear-compose-m3/SKILL.md +365 -0
- package/skills/android-wear-compose-m3/references/android/training/wearables/compose/migrate-to-material3.md +677 -0
- package/skills/android-wear-compose-m3/references/foundation/AmbientModeSample.kt.md +123 -0
- package/skills/android-wear-compose-m3/references/foundation/AmbientModeSample.kt.md.txt +123 -0
- package/skills/android-wear-compose-m3/references/foundation/CurvedWorldSample.kt.md +430 -0
- package/skills/android-wear-compose-m3/references/foundation/CurvedWorldSample.kt.md.txt +430 -0
- package/skills/android-wear-compose-m3/references/foundation/ExpandableSample.kt.md +99 -0
- package/skills/android-wear-compose-m3/references/foundation/ExpandableSample.kt.md.txt +99 -0
- package/skills/android-wear-compose-m3/references/foundation/HierarchicalFocusSample.kt.md +141 -0
- package/skills/android-wear-compose-m3/references/foundation/HierarchicalFocusSample.kt.md.txt +141 -0
- package/skills/android-wear-compose-m3/references/foundation/PagerSamples.kt.md +56 -0
- package/skills/android-wear-compose-m3/references/foundation/PagerSamples.kt.md.txt +56 -0
- package/skills/android-wear-compose-m3/references/foundation/RotarySamples.kt.md +153 -0
- package/skills/android-wear-compose-m3/references/foundation/RotarySamples.kt.md.txt +153 -0
- package/skills/android-wear-compose-m3/references/foundation/ScalingLazyColumnSample.kt.md +131 -0
- package/skills/android-wear-compose-m3/references/foundation/ScalingLazyColumnSample.kt.md.txt +131 -0
- package/skills/android-wear-compose-m3/references/foundation/SwipeToDismissBoxSample.kt.md +169 -0
- package/skills/android-wear-compose-m3/references/foundation/SwipeToDismissBoxSample.kt.md.txt +169 -0
- package/skills/android-wear-compose-m3/references/foundation/SwipeToRevealSample.kt.md +282 -0
- package/skills/android-wear-compose-m3/references/foundation/SwipeToRevealSample.kt.md.txt +282 -0
- package/skills/android-wear-compose-m3/references/foundation/TransformingLazyColumnSample.kt.md +335 -0
- package/skills/android-wear-compose-m3/references/foundation/TransformingLazyColumnSample.kt.md.txt +335 -0
- package/skills/android-wear-compose-m3/references/material3/AlertDialogSample.kt.md +377 -0
- package/skills/android-wear-compose-m3/references/material3/AlertDialogSample.kt.md.txt +377 -0
- package/skills/android-wear-compose-m3/references/material3/AnimatedTextSample.kt.md +165 -0
- package/skills/android-wear-compose-m3/references/material3/AnimatedTextSample.kt.md.txt +165 -0
- package/skills/android-wear-compose-m3/references/material3/ButtonGroupSample.kt.md +91 -0
- package/skills/android-wear-compose-m3/references/material3/ButtonGroupSample.kt.md.txt +91 -0
- package/skills/android-wear-compose-m3/references/material3/ButtonSample.kt.md +496 -0
- package/skills/android-wear-compose-m3/references/material3/ButtonSample.kt.md.txt +496 -0
- package/skills/android-wear-compose-m3/references/material3/CardSample.kt.md +470 -0
- package/skills/android-wear-compose-m3/references/material3/CardSample.kt.md.txt +470 -0
- package/skills/android-wear-compose-m3/references/material3/CheckboxButtonSample.kt.md +67 -0
- package/skills/android-wear-compose-m3/references/material3/CheckboxButtonSample.kt.md.txt +67 -0
- package/skills/android-wear-compose-m3/references/material3/ConfirmationDialogSample.kt.md +162 -0
- package/skills/android-wear-compose-m3/references/material3/ConfirmationDialogSample.kt.md.txt +162 -0
- package/skills/android-wear-compose-m3/references/material3/CurvedTextSamples.kt.md +78 -0
- package/skills/android-wear-compose-m3/references/material3/CurvedTextSamples.kt.md.txt +78 -0
- package/skills/android-wear-compose-m3/references/material3/DatePickerSample.kt.md +131 -0
- package/skills/android-wear-compose-m3/references/material3/DatePickerSample.kt.md.txt +131 -0
- package/skills/android-wear-compose-m3/references/material3/DynamicColorSchemeSample.kt.md +74 -0
- package/skills/android-wear-compose-m3/references/material3/DynamicColorSchemeSample.kt.md.txt +74 -0
- package/skills/android-wear-compose-m3/references/material3/EdgeButtonSample.kt.md +63 -0
- package/skills/android-wear-compose-m3/references/material3/EdgeButtonSample.kt.md.txt +63 -0
- package/skills/android-wear-compose-m3/references/material3/FadingExpandingLabelSample.kt.md +60 -0
- package/skills/android-wear-compose-m3/references/material3/FadingExpandingLabelSample.kt.md.txt +60 -0
- package/skills/android-wear-compose-m3/references/material3/IconButtonSample.kt.md +125 -0
- package/skills/android-wear-compose-m3/references/material3/IconButtonSample.kt.md.txt +125 -0
- package/skills/android-wear-compose-m3/references/material3/IconToggleButtonSample.kt.md +116 -0
- package/skills/android-wear-compose-m3/references/material3/IconToggleButtonSample.kt.md.txt +116 -0
- package/skills/android-wear-compose-m3/references/material3/LevelIndicatorSample.kt.md +68 -0
- package/skills/android-wear-compose-m3/references/material3/LevelIndicatorSample.kt.md.txt +68 -0
- package/skills/android-wear-compose-m3/references/material3/LinearProgressIndicatorSample.kt.md +50 -0
- package/skills/android-wear-compose-m3/references/material3/LinearProgressIndicatorSample.kt.md.txt +50 -0
- package/skills/android-wear-compose-m3/references/material3/ListHeaderSample.kt.md +177 -0
- package/skills/android-wear-compose-m3/references/material3/ListHeaderSample.kt.md.txt +177 -0
- package/skills/android-wear-compose-m3/references/material3/OneHandedGestureSamples.kt.md +651 -0
- package/skills/android-wear-compose-m3/references/material3/OneHandedGestureSamples.kt.md.txt +651 -0
- package/skills/android-wear-compose-m3/references/material3/OpenOnPhoneDialogSample.kt.md +57 -0
- package/skills/android-wear-compose-m3/references/material3/OpenOnPhoneDialogSample.kt.md.txt +57 -0
- package/skills/android-wear-compose-m3/references/material3/PageIndicatorSample.kt.md +110 -0
- package/skills/android-wear-compose-m3/references/material3/PageIndicatorSample.kt.md.txt +110 -0
- package/skills/android-wear-compose-m3/references/material3/PagerScaffoldSample.kt.md +204 -0
- package/skills/android-wear-compose-m3/references/material3/PagerScaffoldSample.kt.md.txt +204 -0
- package/skills/android-wear-compose-m3/references/material3/PickerGroupSample.kt.md +139 -0
- package/skills/android-wear-compose-m3/references/material3/PickerGroupSample.kt.md.txt +139 -0
- package/skills/android-wear-compose-m3/references/material3/PickerSample.kt.md +111 -0
- package/skills/android-wear-compose-m3/references/material3/PickerSample.kt.md.txt +111 -0
- package/skills/android-wear-compose-m3/references/material3/PlaceholderSample.kt.md +184 -0
- package/skills/android-wear-compose-m3/references/material3/PlaceholderSample.kt.md.txt +184 -0
- package/skills/android-wear-compose-m3/references/material3/ProgressIndicatorSample.kt.md +263 -0
- package/skills/android-wear-compose-m3/references/material3/ProgressIndicatorSample.kt.md.txt +263 -0
- package/skills/android-wear-compose-m3/references/material3/RadioButtonSample.kt.md +105 -0
- package/skills/android-wear-compose-m3/references/material3/RadioButtonSample.kt.md.txt +105 -0
- package/skills/android-wear-compose-m3/references/material3/ScaffoldSample.kt.md +146 -0
- package/skills/android-wear-compose-m3/references/material3/ScaffoldSample.kt.md.txt +146 -0
- package/skills/android-wear-compose-m3/references/material3/ScrollAwaySample.kt.md +97 -0
- package/skills/android-wear-compose-m3/references/material3/ScrollAwaySample.kt.md.txt +97 -0
- package/skills/android-wear-compose-m3/references/material3/ScrollIndicatorSample.kt.md +66 -0
- package/skills/android-wear-compose-m3/references/material3/ScrollIndicatorSample.kt.md.txt +66 -0
- package/skills/android-wear-compose-m3/references/material3/SliderSample.kt.md +86 -0
- package/skills/android-wear-compose-m3/references/material3/SliderSample.kt.md.txt +86 -0
- package/skills/android-wear-compose-m3/references/material3/StepperSample.kt.md +148 -0
- package/skills/android-wear-compose-m3/references/material3/StepperSample.kt.md.txt +148 -0
- package/skills/android-wear-compose-m3/references/material3/SurfaceTransformationSample.kt.md +166 -0
- package/skills/android-wear-compose-m3/references/material3/SurfaceTransformationSample.kt.md.txt +166 -0
- package/skills/android-wear-compose-m3/references/material3/SwipeToDismissBoxSample.kt.md +172 -0
- package/skills/android-wear-compose-m3/references/material3/SwipeToDismissBoxSample.kt.md.txt +172 -0
- package/skills/android-wear-compose-m3/references/material3/SwipeToRevealSample.kt.md +367 -0
- package/skills/android-wear-compose-m3/references/material3/SwipeToRevealSample.kt.md.txt +367 -0
- package/skills/android-wear-compose-m3/references/material3/SwitchButtonSample.kt.md +66 -0
- package/skills/android-wear-compose-m3/references/material3/SwitchButtonSample.kt.md.txt +66 -0
- package/skills/android-wear-compose-m3/references/material3/TextButtonSample.kt.md +115 -0
- package/skills/android-wear-compose-m3/references/material3/TextButtonSample.kt.md.txt +115 -0
- package/skills/android-wear-compose-m3/references/material3/TextToggleButtonSample.kt.md +71 -0
- package/skills/android-wear-compose-m3/references/material3/TextToggleButtonSample.kt.md.txt +71 -0
- package/skills/android-wear-compose-m3/references/material3/TimePickerSample.kt.md +151 -0
- package/skills/android-wear-compose-m3/references/material3/TimePickerSample.kt.md.txt +151 -0
- package/skills/android-wear-compose-m3/references/material3/TimeTextSample.kt.md +65 -0
- package/skills/android-wear-compose-m3/references/material3/TimeTextSample.kt.md.txt +65 -0
- package/skills/android-wear-compose-m3/references/material3/TransformationSpecSample.kt.md +246 -0
- package/skills/android-wear-compose-m3/references/material3/TransformationSpecSample.kt.md.txt +246 -0
- package/skills/android-wear-compose-m3/references/material3/TransformingLazyColumnNotificationsSample.kt.md +89 -0
- package/skills/android-wear-compose-m3/references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt +89 -0
- package/skills/android-wear-compose-m3/references/material3/TransformingLazyColumnSample.kt.md +309 -0
- package/skills/android-wear-compose-m3/references/material3/TransformingLazyColumnSample.kt.md.txt +309 -0
- package/skills/android-wear-compose-m3/references/navigation3/SwipeDismissableSceneStrategySample.kt.md +205 -0
- package/skills/android-wear-compose-m3/references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt +205 -0
- package/skills/{architecture-feature-first → flutter-architecture-feature-first}/SKILL.md +1 -1
- package/skills/{bloc → flutter-bloc}/SKILL.md +1 -1
- package/skills/flutter-build-debug/SKILL.md +66 -0
- package/skills/{code-review → flutter-code-review}/SKILL.md +1 -1
- package/skills/{dart-3-updates → flutter-dart-3-updates}/SKILL.md +1 -1
- package/skills/{dart-fix-runtime-errors → flutter-dart-fix-runtime-errors}/SKILL.md +1 -1
- package/skills/{dart-resolve-package-conflicts → flutter-dart-resolve-package-conflicts}/SKILL.md +1 -1
- package/skills/{dart-run-static-analysis → flutter-dart-run-static-analysis}/SKILL.md +1 -1
- package/skills/{dart-use-pattern-matching → flutter-dart-use-pattern-matching}/SKILL.md +1 -1
- package/skills/{effective-dart → flutter-effective-dart}/SKILL.md +1 -1
- package/skills/{provider → flutter-provider}/SKILL.md +1 -1
- package/skills/{riverpod → flutter-riverpod}/SKILL.md +1 -1
- package/skills/ios-cocoapods-debug/SKILL.md +65 -0
- package/skills/ios-code-review/SKILL.md +56 -0
- package/skills/ios-xcode-build-debug/SKILL.md +66 -0
- package/skills/{detect-mobile-stack → mobile-detect-stack}/SKILL.md +1 -1
- package/skills/mobile-firebase/SKILL.md +54 -0
- package/skills/mobile-firebase/references/android/ai-logic.md +31 -0
- package/skills/mobile-firebase/references/android/analytics.md +33 -0
- package/skills/mobile-firebase/references/android/app-check.md +36 -0
- package/skills/mobile-firebase/references/android/auth.md +44 -0
- package/skills/mobile-firebase/references/android/crashlytics.md +31 -0
- package/skills/mobile-firebase/references/android/firestore.md +44 -0
- package/skills/mobile-firebase/references/android/functions.md +33 -0
- package/skills/mobile-firebase/references/android/in-app-messaging.md +28 -0
- package/skills/mobile-firebase/references/android/messaging.md +41 -0
- package/skills/mobile-firebase/references/android/realtime-database.md +50 -0
- package/skills/mobile-firebase/references/android/remote-config.md +43 -0
- package/skills/mobile-firebase/references/android/sql-connect.md +31 -0
- package/skills/mobile-firebase/references/android/storage.md +39 -0
- package/skills/mobile-firebase/references/android.md +30 -0
- package/skills/{firebase-ai/SKILL.md → mobile-firebase/references/flutter/ai-logic.md} +2 -8
- package/skills/{firebase-analytics/SKILL.md → mobile-firebase/references/flutter/analytics.md} +2 -8
- package/skills/{firebase-app-check/SKILL.md → mobile-firebase/references/flutter/app-check.md} +2 -8
- package/skills/{firebase-auth/SKILL.md → mobile-firebase/references/flutter/auth.md} +2 -8
- package/skills/{firebase-crashlytics/SKILL.md → mobile-firebase/references/flutter/crashlytics.md} +2 -8
- package/skills/{firebase-cloud-firestore/SKILL.md → mobile-firebase/references/flutter/firestore.md} +2 -8
- package/skills/{firebase-cloud-functions/SKILL.md → mobile-firebase/references/flutter/functions.md} +2 -8
- package/skills/{firebase-in-app-messaging/SKILL.md → mobile-firebase/references/flutter/in-app-messaging.md} +2 -8
- package/skills/{firebase-messaging/SKILL.md → mobile-firebase/references/flutter/messaging.md} +2 -8
- package/skills/{firebase-database/SKILL.md → mobile-firebase/references/flutter/realtime-database.md} +2 -8
- package/skills/{firebase-remote-config/SKILL.md → mobile-firebase/references/flutter/remote-config.md} +2 -8
- package/skills/{flutterfire-configure/SKILL.md → mobile-firebase/references/flutter/setup-flutterfire.md} +1 -8
- package/skills/{firebase-data-connect/SKILL.md → mobile-firebase/references/flutter/sql-connect.md} +2 -8
- package/skills/{firebase-storage/SKILL.md → mobile-firebase/references/flutter/storage.md} +2 -8
- package/skills/mobile-firebase/references/flutter.md +36 -0
- package/skills/mobile-firebase/references/ios/ai-logic.md +30 -0
- package/skills/mobile-firebase/references/ios/analytics.md +33 -0
- package/skills/mobile-firebase/references/ios/app-check.md +36 -0
- package/skills/mobile-firebase/references/ios/auth.md +48 -0
- package/skills/mobile-firebase/references/ios/crashlytics.md +34 -0
- package/skills/mobile-firebase/references/ios/firestore.md +53 -0
- package/skills/mobile-firebase/references/ios/functions.md +35 -0
- package/skills/mobile-firebase/references/ios/in-app-messaging.md +26 -0
- package/skills/mobile-firebase/references/ios/messaging.md +45 -0
- package/skills/mobile-firebase/references/ios/realtime-database.md +49 -0
- package/skills/mobile-firebase/references/ios/remote-config.md +44 -0
- package/skills/mobile-firebase/references/ios/sql-connect.md +33 -0
- package/skills/mobile-firebase/references/ios/storage.md +36 -0
- package/skills/mobile-firebase/references/ios.md +28 -0
- package/skills/mobile-firebase/references/react-native/ai-logic.md +32 -0
- package/skills/mobile-firebase/references/react-native/analytics.md +43 -0
- package/skills/mobile-firebase/references/react-native/app-check.md +35 -0
- package/skills/mobile-firebase/references/react-native/auth.md +50 -0
- package/skills/mobile-firebase/references/react-native/crashlytics.md +36 -0
- package/skills/mobile-firebase/references/react-native/firestore.md +45 -0
- package/skills/mobile-firebase/references/react-native/functions.md +28 -0
- package/skills/mobile-firebase/references/react-native/in-app-messaging.md +27 -0
- package/skills/mobile-firebase/references/react-native/messaging.md +46 -0
- package/skills/mobile-firebase/references/react-native/realtime-database.md +46 -0
- package/skills/mobile-firebase/references/react-native/remote-config.md +32 -0
- package/skills/mobile-firebase/references/react-native/sql-connect.md +11 -0
- package/skills/mobile-firebase/references/react-native/storage.md +30 -0
- package/skills/mobile-firebase/references/react-native.md +29 -0
- package/skills/mobile-test/SKILL.md +63 -0
- package/skills/mobile-test/references/android/setup/GUIDE.md +183 -0
- package/skills/mobile-test/references/android/setup/references/android/develop/ui/compose/testing/common-patterns.md +181 -0
- package/skills/mobile-test/references/android/setup/references/android/studio/preview/compose-screenshot-testing.md +255 -0
- package/skills/mobile-test/references/android/setup/references/android/training/dependency-injection/hilt-testing.md +447 -0
- package/skills/mobile-test/references/android.md +83 -0
- package/skills/{dart-collect-coverage/SKILL.md → mobile-test/references/flutter/coverage.md} +2 -11
- package/skills/{dart-generate-test-mocks/SKILL.md → mobile-test/references/flutter/generate-mocks.md} +2 -11
- package/skills/{flutter-add-integration-test/SKILL.md → mobile-test/references/flutter/integration-tests.md} +2 -11
- package/skills/{dart-migrate-to-checks-package/SKILL.md → mobile-test/references/flutter/migrate-to-checks.md} +2 -13
- package/skills/{mockito/SKILL.md → mobile-test/references/flutter/mockito.md} +1 -8
- package/skills/{mocktail/SKILL.md → mobile-test/references/flutter/mocktail.md} +1 -8
- package/skills/{patrol-e2e-testing/SKILL.md → mobile-test/references/flutter/patrol.md} +1 -8
- package/skills/{testing/SKILL.md → mobile-test/references/flutter/testing-guidelines.md} +1 -8
- package/skills/{dart-add-unit-test/SKILL.md → mobile-test/references/flutter/unit-tests.md} +2 -11
- package/skills/{flutter-add-widget-test/SKILL.md → mobile-test/references/flutter/widget-tests.md} +2 -11
- package/skills/mobile-test/references/flutter.md +44 -0
- package/skills/mobile-test/references/ios.md +79 -0
- package/skills/mobile-test/references/react-native.md +62 -0
- /package/skills/{dart-use-pattern-matching → flutter-dart-use-pattern-matching}/examples/json_patterns.dart +0 -0
package/skills/android-restore-credentials/references/android/identity/passkeys/create-passkeys.md
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
Before your users can authenticate with passkeys, your app must first register
|
|
2
|
+
or create the passkey for their account.
|
|
3
|
+
|
|
4
|
+
To create the passkey, obtain details required to create the passkey from your
|
|
5
|
+
app server, and then call the Credential Manager API, which returns a public and
|
|
6
|
+
private key pair. The returned private key is stored in a credential provider,
|
|
7
|
+
such as Google Password Manager, as a passkey. The public key is stored on your
|
|
8
|
+
app server.
|
|
9
|
+
|
|
10
|
+
> [!TIP]
|
|
11
|
+
> **Tip:** While designing authentication flows with passkeys, make sure that you follow the [UX guidelines for passkeys](https://developer.android.com/design/ui/mobile/guides/patterns/passkeys).
|
|
12
|
+
|
|
13
|
+
 **Figure 1:**Creation of passkeys
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
Make sure that you have set up [Digital Asset Links](https://developer.android.com/identity/credential-manager/prerequisites) and that you target
|
|
18
|
+
devices running Android 9 (API level 28) or higher.
|
|
19
|
+
|
|
20
|
+
## Overview
|
|
21
|
+
|
|
22
|
+
This guide focuses on the changes required in your [relying party client app](https://developer.android.com/identity/credential-manager#authentication-terminology)
|
|
23
|
+
to create a passkey, and gives a brief overview of the [relying party app
|
|
24
|
+
server](https://developer.android.com/identity/credential-manager#authentication-terminology) implementation. To learn more about the server-side integration, see
|
|
25
|
+
[Server-side passkey registration](https://developers.google.com/identity/passkeys/developer-guides/server-registration).
|
|
26
|
+
|
|
27
|
+
1. [**Add dependencies to your app**](https://developer.android.com/identity/passkeys/create-passkeys#add-dependencies): Add the required Credential Manager libraries.
|
|
28
|
+
2. [**Instantiate Credential Manager**](https://developer.android.com/identity/passkeys/create-passkeys#instantiate): Create a Credential Manager instance.
|
|
29
|
+
3. [**Get credential creation options from the app server**](https://developer.android.com/identity/passkeys/create-passkeys#get-options): From your app server, send the client app the details required to create the passkey, such as information about the app, the user, as well as a `challenge` and other fields.
|
|
30
|
+
4. [**Request a passkey**](https://developer.android.com/identity/passkeys/create-passkeys#request-passkey): In your app, use the details received from the app server to create a [`GetPublicKeyCredentialOption`](https://developer.android.com/reference/androidx/credentials/GetPublicKeyCredentialOption) object and use this object to invoke the `credentialManager.getCredential()` method to create a passkey.
|
|
31
|
+
5. [**Handle the passkey creation response**](https://developer.android.com/identity/passkeys/create-passkeys#handle-response): When you receive the credentials on your client app, you must encode, serialize and then send the public key to the app server. You must also handle each of the exceptions that can occur in case of passkey creation.
|
|
32
|
+
6. [**Verify and save the public key on the server**](https://developer.android.com/identity/passkeys/create-passkeys#verify): Complete the server-side steps to verify the origin of the credential and then save the public key.
|
|
33
|
+
7. [**Notify the user**](https://developer.android.com/identity/passkeys/create-passkeys#notify): Notify the user that their passkey has been created.
|
|
34
|
+
|
|
35
|
+
> [!TIP]
|
|
36
|
+
> **Tip:** To enhance the user experience during sign up, add functionality to [restore credentials](https://developer.android.com/identity/sign-in/restore-credentials) on a new device to let users seamlessly set up their existing accounts on new Android devices, and [suppressing autofill dialogs on
|
|
37
|
+
> credential fields](https://developer.android.com/identity/passkeys/create-passkeys#suppress-autofill).
|
|
38
|
+
|
|
39
|
+
## Add dependencies to your app
|
|
40
|
+
|
|
41
|
+
Add the following dependencies to your app module's `build.gradle` file:
|
|
42
|
+
|
|
43
|
+
### Kotlin
|
|
44
|
+
|
|
45
|
+
```kotlin
|
|
46
|
+
dependencies {
|
|
47
|
+
implementation("androidx.credentials:credentials:1.7.0-alpha03")
|
|
48
|
+
implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha03")
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Groovy
|
|
53
|
+
|
|
54
|
+
```groovy
|
|
55
|
+
dependencies {
|
|
56
|
+
implementation "androidx.credentials:credentials:1.7.0-alpha03"
|
|
57
|
+
implementation "androidx.credentials:credentials-play-services-auth:1.7.0-alpha03"
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
> [!NOTE]
|
|
62
|
+
> **Note:** Use the latest available versions of the dependencies. Versions of [`androidx.credentials`](https://developer.android.com/identity/passkeys/create-passkeys#automatic-upgrade) earlier than version 1.2 throw an `UnsupportedOperationException("Post-U not supported yet")` exception on Android 14.
|
|
63
|
+
|
|
64
|
+
## Instantiate Credential Manager
|
|
65
|
+
|
|
66
|
+
Use your app or activity context to create a `CredentialManager` object.
|
|
67
|
+
|
|
68
|
+
// Use your app or activity context to instantiate a client instance of
|
|
69
|
+
// CredentialManager.
|
|
70
|
+
private val credentialManager = CredentialManager.create(context)
|
|
71
|
+
|
|
72
|
+
## Get credential creation options from your app server
|
|
73
|
+
|
|
74
|
+
When the user clicks a "Create Passkey" button or when a new user signs up, make
|
|
75
|
+
a request from your app to your app server to obtain the information required to
|
|
76
|
+
start the passkey registration process.
|
|
77
|
+
|
|
78
|
+
Use a FIDO-compliant library in your app server to send your client app the
|
|
79
|
+
information required to create a passkey, such as information about the user,
|
|
80
|
+
the app, and additional configuration properties. To learn more, see [Server
|
|
81
|
+
side passkey registration](https://developers.google.com/identity/passkeys/developer-guides/server-registration).
|
|
82
|
+
|
|
83
|
+
In the client app, decode the public key creation options sent by the app
|
|
84
|
+
server. These are usually represented in JSON format. To learn more about how
|
|
85
|
+
this decoding is done for web clients, see [Encoding and
|
|
86
|
+
Decoding](https://developers.google.com/identity/passkeys/developer-guides/server-registration#encoding_and_decoding). For Android client apps, you must handle the decoding
|
|
87
|
+
separately.
|
|
88
|
+
|
|
89
|
+
> [!NOTE]
|
|
90
|
+
> **Note:** On your app server, securely store the `challenge` so that you can later verify the origin of the credential.
|
|
91
|
+
|
|
92
|
+
The following snippet shows the structure the public key creation options sent
|
|
93
|
+
by the app server:
|
|
94
|
+
|
|
95
|
+
{
|
|
96
|
+
"challenge": "<base64url-encoded challenge>",
|
|
97
|
+
"rp": {
|
|
98
|
+
"name": "<relying party name>",
|
|
99
|
+
"id": "<relying party host name>"
|
|
100
|
+
},
|
|
101
|
+
"user": {
|
|
102
|
+
"id": "<base64url-encoded user ID>",
|
|
103
|
+
"name": "<user name>",
|
|
104
|
+
"displayName": "<user display name>"
|
|
105
|
+
},
|
|
106
|
+
"pubKeyCredParams": [
|
|
107
|
+
{
|
|
108
|
+
"type": "public-key",
|
|
109
|
+
"alg": -7
|
|
110
|
+
}
|
|
111
|
+
],
|
|
112
|
+
"attestation": "none",
|
|
113
|
+
"excludeCredentials": [
|
|
114
|
+
{
|
|
115
|
+
"id": "<base64url-encoded credential ID to exclude>",
|
|
116
|
+
"type": "public-key"
|
|
117
|
+
}
|
|
118
|
+
],
|
|
119
|
+
"authenticatorSelection": {
|
|
120
|
+
"requireResidentKey": true,
|
|
121
|
+
"residentKey": "required",
|
|
122
|
+
"userVerification": "required"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
Key fields in the public key creation options include:
|
|
127
|
+
|
|
128
|
+
- `challenge`: A server-generated random string that is used to prevent replay attacks.
|
|
129
|
+
- `rp`: Details about the app.
|
|
130
|
+
- `rp.name`: The app's name.
|
|
131
|
+
- `rp.id`: The app's domain or subdomain.
|
|
132
|
+
- `user`: Details about the user.
|
|
133
|
+
- `id`: The user's unique ID. This value must not include personally identifying information, for example, email addresses or usernames. You can use a random, 16-byte value.
|
|
134
|
+
- `name`: A unique identifier for the account that the user will recognise, such as their email address or username. This will be displayed in the account selector. If using a username, use the same value as in password authentication.
|
|
135
|
+
- `displayName`: An optional, user-friendly name for the account intended for display in the account selector.
|
|
136
|
+
- `authenticatorSelection`: Details about the device that will be used for authentication.
|
|
137
|
+
- `authenticatorAttachment`: Indicates the preferred [authenticator](https://www.w3.org/TR/webauthn/#authenticator). The possible values are as follows:
|
|
138
|
+
- `platform`: This value is used for an authenticator built into the user's device, such as a fingerprint sensor.
|
|
139
|
+
- `cross-platform`: This value is used for roaming devices such as security keys. It is not typically used in the passkey context.
|
|
140
|
+
- Unspecified (recommended): Leaving this value unspecified provides users with the flexibility to create passkeys on their preferred devices. In most cases, leaving the parameter unspecified is the best option.
|
|
141
|
+
- `requireResidentKey`: To create a passkey, set the value of this `Boolean` field to `true`.
|
|
142
|
+
- `residentKey`: To create a passkey, set the value to `required`.
|
|
143
|
+
- `userVerification`: Used to specify the requirements for user verification during a passkey registration. The possible values are as follows:
|
|
144
|
+
- `preferred`: Use this value if you prioritize user experience over protection, such as in environments where user verification causes more friction than protection.
|
|
145
|
+
- `required`: Use this value if invoking a user verification method available on the device is required.
|
|
146
|
+
- `discouraged`: Use this value if using a user verification method is discouraged.
|
|
147
|
+
To learn more about `userVerification`, see [userVerification deep dive](https://web.dev/articles/webauthn-user-verification).
|
|
148
|
+
- `excludeCredentials`: List credential IDs in an [array](https://w3c.github.io/webauthn/#dom-publickeycredentialcreationoptions-excludecredentials) to prevent the creation of a duplicate passkey if one already exists with the same credential provider.
|
|
149
|
+
|
|
150
|
+
## Create a passkey
|
|
151
|
+
|
|
152
|
+
After you have parsed the server-side public key creation options, create a
|
|
153
|
+
passkey by wrapping these options in a `CreatePublicKeyCredentialRequest` object
|
|
154
|
+
and calling `createCredential()`.
|
|
155
|
+
|
|
156
|
+
The `createPublicKeyCredentialRequest` includes the following:
|
|
157
|
+
|
|
158
|
+
- `requestJson`: The credential creation options sent by the app server.
|
|
159
|
+
- `preferImmediatelyAvailableCredentials`: This is an optional Boolean field that defines whether to only use locally-available or credential provider-synced credentials to fulfill the request, instead of credentials from security keys or [hybrid](https://w3c.github.io/webauthn/#dom-authenticatortransport-hybrid) key flows. The possible usages are as follows:
|
|
160
|
+
- `false` (default): Use this value if the call to Credential Manager was triggered by an explicit user action.
|
|
161
|
+
- `true`: Use this value if Credential Manager is opportunistically called, such as when first opening the app.
|
|
162
|
+
If you set the value to `true` and there are no immediately available credentials, Credential Manager won't show any UI and the request will fail immediately, returning NoCredentialException for get requests and [`CreateCredentialNoCreateOptionException`](https://developer.android.com/reference/kotlin/androidx/credentials/exceptions/CreateCredentialNoCreateOptionException) for create requests.
|
|
163
|
+
- `origin`: This field is automatically set for Android apps. For browsers and similarly privileged apps that need to set `origin`, see [Make Credential
|
|
164
|
+
Manager calls on behalf of other parties for privileged apps](https://developer.android.com/training/sign-in/privileged-apps).
|
|
165
|
+
- `isConditional`: This is an optional field that defaults to `false`. For more information, see [Automatically create a passkey](https://developer.android.com/identity/passkeys/create-passkeys#automatic-upgrade).
|
|
166
|
+
|
|
167
|
+
Calling the `createCredential()` function launches Credential Manager's built-in
|
|
168
|
+
bottom sheet UI that prompts the user to use a passkey and to select a
|
|
169
|
+
credential provider and account for storage. However, if `isConditional` is set
|
|
170
|
+
to `true`, the bottom sheet UI does not display, and the passkey is
|
|
171
|
+
automatically created.
|
|
172
|
+
|
|
173
|
+
### Automatically create a passkey
|
|
174
|
+
|
|
175
|
+
You can automatically create a passkey for a user after a successful password
|
|
176
|
+
login by setting the `isConditional` parameter to `true` in your
|
|
177
|
+
`CreatePublicKeyCredentialRequest` while creating a passkey. If the user doesn't
|
|
178
|
+
already have a passkey, your app will automatically attempt to create one in the
|
|
179
|
+
background and store it in the user's credential provider, such as Google
|
|
180
|
+
Password Manager. For an example of how this is implemented, see the [public
|
|
181
|
+
sample](https://github.com/android/identity-samples/blob/main/Shrine/app/src/main/java/com/authentication/shrine/ui/AuthenticationScreen.kt#L98).
|
|
182
|
+
 **Figure 2:**Google Password Manager notification
|
|
183
|
+
|
|
184
|
+
> [!NOTE]
|
|
185
|
+
> **Note:** If a passkey is created automatically, credential providers are responsible for notifying users about a newly created passkey. Google Password Manager notifies users when a passkey is automatically created. However, other credential providers might have their own conditions and notifications for this feature.
|
|
186
|
+
|
|
187
|
+
## Handle the response
|
|
188
|
+
|
|
189
|
+
After the user is verified using the device's screen lock, a passkey is created
|
|
190
|
+
and stored in the user's selected credential provider.
|
|
191
|
+
|
|
192
|
+
The response after you successfully call `createCredential()` is a
|
|
193
|
+
[PublicKeyCredential](https://developer.android.com/jetpack/androidx/releases/credentials) object.
|
|
194
|
+
|
|
195
|
+
The `PublicKeyCredential` looks as follows:
|
|
196
|
+
|
|
197
|
+
{
|
|
198
|
+
"id": "<identifier>",
|
|
199
|
+
"type": "public-key",
|
|
200
|
+
"rawId": "<identifier>",
|
|
201
|
+
"response": {
|
|
202
|
+
"clientDataJSON": "<ArrayBuffer encoded object with the origin and signed challenge>",
|
|
203
|
+
"attestationObject": "<ArrayBuffer encoded object with the public key and other information.>"
|
|
204
|
+
},
|
|
205
|
+
"authenticatorAttachment": "platform"
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
In the client app, serialize the object and send it to the app server.
|
|
209
|
+
|
|
210
|
+
Add code to handle failures as shown in the following snippet:
|
|
211
|
+
|
|
212
|
+
fun handleFailure(e: CreateCredentialException) {
|
|
213
|
+
when (e) {
|
|
214
|
+
is CreatePublicKeyCredentialDomException -> {
|
|
215
|
+
// Handle the passkey DOM errors thrown according to the
|
|
216
|
+
// WebAuthn spec.
|
|
217
|
+
}
|
|
218
|
+
is CreateCredentialCancellationException -> {
|
|
219
|
+
// The user intentionally canceled the operation and chose not
|
|
220
|
+
// to register the credential.
|
|
221
|
+
}
|
|
222
|
+
is CreateCredentialInterruptedException -> {
|
|
223
|
+
// Retry-able error. Consider retrying the call.
|
|
224
|
+
}
|
|
225
|
+
is CreateCredentialProviderConfigurationException -> {
|
|
226
|
+
// Your app is missing the provider configuration dependency.
|
|
227
|
+
// Most likely, you're missing the
|
|
228
|
+
// "credentials-play-services-auth" module.
|
|
229
|
+
}
|
|
230
|
+
is CreateCredentialCustomException -> {
|
|
231
|
+
// You have encountered an error from a 3rd-party SDK. If you
|
|
232
|
+
// make the API call with a request object that's a subclass of
|
|
233
|
+
// CreateCustomCredentialRequest using a 3rd-party SDK, then you
|
|
234
|
+
// should check for any custom exception type constants within
|
|
235
|
+
// that SDK to match with e.type. Otherwise, drop or log the
|
|
236
|
+
// exception.
|
|
237
|
+
}
|
|
238
|
+
else -> Log.w(TAG, "Unexpected exception type ${e::class.java.name}")
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
## Verify and save the public key on the app server
|
|
243
|
+
|
|
244
|
+
On the app server, you must verify the public key credential and then [save the
|
|
245
|
+
public key](https://web.dev/articles/passkey-registration#save-credential).
|
|
246
|
+
|
|
247
|
+
To verify the public key credential's origin, compare it against an allow list
|
|
248
|
+
of approved apps. If a key has an unrecognized origin, reject it.
|
|
249
|
+
|
|
250
|
+
> [!NOTE]
|
|
251
|
+
> **Note:** An app's origin is based on its unique identity, which is the SHA-256 fingerprint of its signing certificate.
|
|
252
|
+
|
|
253
|
+
To obtain the app's SHA 256 fingerprint:
|
|
254
|
+
|
|
255
|
+
1. Print your release app's signing certificate by running the following
|
|
256
|
+
command in a terminal:
|
|
257
|
+
|
|
258
|
+
keytool -list -keystore <path-to-apk-signing-keystore>
|
|
259
|
+
|
|
260
|
+
In the response, identify the signing certificate's SHA 256 fingerprint,
|
|
261
|
+
mentioned as `Certificate fingerprints block` : `SHA256`.
|
|
262
|
+
2. Encode the SHA256 fingerprint with base64url encoding. This Python example
|
|
263
|
+
demonstrates how to properly encode the fingerprint:
|
|
264
|
+
|
|
265
|
+
import binascii
|
|
266
|
+
import base64
|
|
267
|
+
fingerprint = '<SHA256 finerprint>' # your app's SHA256 fingerprint
|
|
268
|
+
print(base64.urlsafe_b64encode(binascii.a2b_hex(fingerprint.replace(':', ''))).decode('utf8').replace('=', ''))
|
|
269
|
+
|
|
270
|
+
3. Append `android:apk-key-hash`: to the start of the output from the previous
|
|
271
|
+
step so that you get something that is similar to the following:
|
|
272
|
+
|
|
273
|
+
android:apk-key-hash:<encoded SHA 256 fingerprint>
|
|
274
|
+
|
|
275
|
+
The result should match with an allowed origin on your app server. If you
|
|
276
|
+
have multiple signing certificates, such as certificates for debugging and
|
|
277
|
+
release, or multiple apps, then repeat the process and accept all the
|
|
278
|
+
origins as valid on the app server.
|
|
279
|
+
|
|
280
|
+
> [!NOTE]
|
|
281
|
+
> **Note:** When you save the passkey on the app server, make sure that you save the Authenticator Attestation Globally Unique Identifier ([AAGUID](https://web.dev/articles/webauthn-aaguid)) from the client data. The AAGUID is a unique number that identifies the model of the authenticator. For more information, see [Manage passkeys](https://developer.android.com/identity/passkeys/manage-passkeys).
|
|
282
|
+
|
|
283
|
+
## Notify the user
|
|
284
|
+
|
|
285
|
+
After the passkey is successfully created, notify your users about the passkey
|
|
286
|
+
and inform them that they can manage their passkeys from their credential
|
|
287
|
+
provider app or from [within the app settings](https://developer.android.com/identity/passkeys/manage-passkeys). Notify users by using a
|
|
288
|
+
custom dialog, notification, or snackbar. Since an unexpected passkey creation
|
|
289
|
+
by a malicious entity requires an immediate security alert, consider
|
|
290
|
+
supplementing these in-app methods with external communication, such as an
|
|
291
|
+
email.
|
|
292
|
+
|
|
293
|
+
## Enhance the user experience
|
|
294
|
+
|
|
295
|
+
To enhance the user experience while implementing sign up with Credential
|
|
296
|
+
Manager, consider adding functionality for restore credentials and suppress
|
|
297
|
+
autofill dialogs.
|
|
298
|
+
|
|
299
|
+
### Add functionality to restore credentials on a new device
|
|
300
|
+
|
|
301
|
+
To allow users to seamlessly log into their accounts on a new device, implement
|
|
302
|
+
the [Restore Credentials](https://developer.android.com/identity/sign-in/restore-credentials) functionality. Adding restore credentials with
|
|
303
|
+
`BackupAgent` logs users in when they open your restored app on a new device,
|
|
304
|
+
letting them use your app right away.
|
|
305
|
+
|
|
306
|
+
### Suppress autofill on credential fields (optional)
|
|
307
|
+
|
|
308
|
+
For app screens where users are expected to use Credential Manager's bottom
|
|
309
|
+
sheet UI for authentication, add the `isCredential` attribute to the username
|
|
310
|
+
and password fields. This suppresses autofill dialogs (`FillDialog` and
|
|
311
|
+
`SaveDialog`) from overlapping with Credential Manager's bottom sheet UI.
|
|
312
|
+
|
|
313
|
+
The `isCredential` attribute is supported on Android 14 and higher.
|
|
314
|
+
|
|
315
|
+
The following example demonstrates how you can add the `isCredential` attribute
|
|
316
|
+
to the relevant username and password fields in the relevant views for your app:
|
|
317
|
+
|
|
318
|
+
<TextView
|
|
319
|
+
android:layout_width="match_parent"
|
|
320
|
+
android:layout_height="wrap_content"
|
|
321
|
+
android:isCredential="true" /\>
|
|
322
|
+
|
|
323
|
+
## Next steps
|
|
324
|
+
|
|
325
|
+
- [Sign in with passkeys](https://developer.android.com/identity/passkeys/sign-in-with-passkeys)
|
|
326
|
+
- [Manage passkeys](https://developer.android.com/identity/passkeys/manage-passkeys)
|
|
327
|
+
- [Understand passkey user experience flows](https://developer.android.com/design/ui/mobile/guides/patterns/passkeys)
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
This guide continues on the implementation of using passkeys for authentication.
|
|
2
|
+
Before your users can sign in with passkeys, you must also complete the
|
|
3
|
+
instructions in [Create passkeys](https://developer.android.com/identity/passkeys/create-passkeys).
|
|
4
|
+
|
|
5
|
+
To authenticate with a passkey, you must first retrieve the options required to
|
|
6
|
+
retrieve the public key from your [app server](https://developer.android.com/identity/credential-manager#authentication-terminology), and then call the Credential
|
|
7
|
+
Manager API to retrieve the public key. Then, handle the sign-in response
|
|
8
|
+
appropriately.
|
|
9
|
+
|
|
10
|
+
> [!TIP]
|
|
11
|
+
> **Tip:** While designing authentication flows with passkeys, make sure you follow the recommendations in the [UX guidelines for passkeys](https://developer.android.com/design/ui/mobile/guides/patterns/passkeys).
|
|
12
|
+
|
|
13
|
+
## Overview
|
|
14
|
+
|
|
15
|
+
This guide focuses on the changes required in your client app to sign in your
|
|
16
|
+
user with a passkey, and gives a brief overview of the app server-side
|
|
17
|
+
implementation. To learn more about server-side integration, see [Server-side
|
|
18
|
+
passkey authentication](https://developers.google.com/identity/passkeys/developer-guides/server-authentication).
|
|
19
|
+
|
|
20
|
+
To retrieve all the passkey and password options that are associated with the
|
|
21
|
+
user's account, complete these steps:
|
|
22
|
+
|
|
23
|
+
1. [**Get credential request options from the server**](https://developer.android.com/identity/passkeys/sign-in-with-passkeys#get-options): Make a request from your app to your authentication server to start the passkey sign-in process. From the server, send the options required to get the public key credential, as well as a unique challenge.
|
|
24
|
+
2. [**Create the object required to get the public key credential**](https://developer.android.com/identity/passkeys/sign-in-with-passkeys#create-object): Wrap the options sent by the server in a `GetPublicKeyCredentialOption` object
|
|
25
|
+
3. ([**optional) Prepare getCredential**](https://developer.android.com/identity/passkeys/sign-in-with-passkeys#reduce-latency): In Android 14 and higher, you can reduce latency by showing the account selector by using the `prepareGetCredential()` method before calling `getCredential()`.
|
|
26
|
+
4. [**Launch the sign in flow**](https://developer.android.com/identity/passkeys/sign-in-with-passkeys#launch-sign-in): Call `getCredential()` method to sign in the user
|
|
27
|
+
5. [**Handle the response**](https://developer.android.com/identity/passkeys/sign-in-with-passkeys#handle-response): Handle each of the possible credential responses.
|
|
28
|
+
6. [**Handle exceptions**](https://developer.android.com/identity/passkeys/sign-in-with-passkeys#handle-exceptions): Make sure that you handle exceptions appropriately.
|
|
29
|
+
|
|
30
|
+
> [!TIP]
|
|
31
|
+
> **Tip:** Enhance the user experience during sign in by also adding functionality to [restore credentials](https://developer.android.com/identity/sign-in/restore-credentials) on a new device to let users seamlessly set up their existing accounts on new Android devices.
|
|
32
|
+
|
|
33
|
+
## Get credential request options from the server
|
|
34
|
+
|
|
35
|
+
Request the server for the options required to get the public key credentials,
|
|
36
|
+
as well as the `challenge`, which is unique for each sign-in attempt. To learn
|
|
37
|
+
more about the server-side implementation, see [Create the
|
|
38
|
+
challenge](https://developers.google.com/identity/passkeys/developer-guides/server-authentication#create_the_challenge) and [Create credential request
|
|
39
|
+
options](https://developers.google.com/identity/passkeys/developer-guides/server-authentication#create_credential_request_options).
|
|
40
|
+
|
|
41
|
+
The options look similar to the following:
|
|
42
|
+
|
|
43
|
+
{
|
|
44
|
+
"challenge": "<your app challenge>",
|
|
45
|
+
"allowCredentials": [],
|
|
46
|
+
"rpId": "<your app server domain>"
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
To learn more about the fields, see the blogpost about [signing in with a
|
|
50
|
+
passkey](https://web.dev/articles/passkey-form-autofill#fetch_information_from_the_backend).
|
|
51
|
+
|
|
52
|
+
> [!TIP]
|
|
53
|
+
> **Tip:** To reduce wait times in the UI because of as network calls, fetch the details required from the app server at the beginning of the user's app session.
|
|
54
|
+
|
|
55
|
+
## Create the object required to get the public key credential
|
|
56
|
+
|
|
57
|
+
In your app, use the options to create a `GetPublicKeyCredentialOption` object.
|
|
58
|
+
In the following example, `requestJson` represents the options sent by the
|
|
59
|
+
server.
|
|
60
|
+
|
|
61
|
+
// Get password logins from the credential provider on the user's device.
|
|
62
|
+
val getPasswordOption = GetPasswordOption()
|
|
63
|
+
|
|
64
|
+
// Get passkeys from the credential provider on the user's device.
|
|
65
|
+
val getPublicKeyCredentialOption = GetPublicKeyCredentialOption(
|
|
66
|
+
requestJson = requestJson
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
Then, wrap `GetPublicKeyCredentialOption` in a `GetCredentialRequest` object.
|
|
70
|
+
|
|
71
|
+
val credentialRequest = GetCredentialRequest(
|
|
72
|
+
// Include all the sign-in options that your app supports.
|
|
73
|
+
listOf(getPasswordOption, getPublicKeyCredentialOption),
|
|
74
|
+
// Defines whether you prefer to use only immediately available
|
|
75
|
+
// credentials or hybrid credentials.
|
|
76
|
+
preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
> [!NOTE]
|
|
80
|
+
> **Note:** [`GetCredentialRequest`](https://developer.android.com/reference/androidx/credentials/GetCredentialRequest#GetCredentialRequest) can include an `origin` field. However, `origin` is automatically set for Android apps, and hence should be left as null. For browsers and similarly privileged apps that need to set `origin`, see [Make Credential Manager calls on behalf of other parties for privileged
|
|
81
|
+
> apps](https://developer.android.com/training/sign-in/privileged-apps).
|
|
82
|
+
|
|
83
|
+
## Optional: Reduce sign-in latency
|
|
84
|
+
|
|
85
|
+
On Android 14 or higher, you can reduce latency when showing the account
|
|
86
|
+
selector by using the [`prepareGetCredential()`](https://developer.android.com/reference/androidx/credentials/CredentialManager#prepareGetCredential) method before calling
|
|
87
|
+
`getCredential()`.
|
|
88
|
+
|
|
89
|
+
The `prepareGetCredential()` method returns a
|
|
90
|
+
[`PrepareGetCredentialResponse`](https://developer.android.com/reference/androidx/credentials/PrepareGetCredentialResponse) object which is cached. This lets the
|
|
91
|
+
`getCredential()` method in the following step bring up the account selector
|
|
92
|
+
with the cached data.
|
|
93
|
+
|
|
94
|
+
coroutineScope {
|
|
95
|
+
val response = credentialManager.prepareGetCredential(
|
|
96
|
+
GetCredentialRequest(
|
|
97
|
+
listOf(
|
|
98
|
+
// Include all the sign-in options that your app supports
|
|
99
|
+
getPublicKeyCredentialOption,
|
|
100
|
+
getPasswordOption
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
## Launch the sign-in flow
|
|
107
|
+
|
|
108
|
+
Call the `getCredential()` method to show the user the account selector. Use the
|
|
109
|
+
following code snippet as a reference for how to launch the sign-in flow:
|
|
110
|
+
|
|
111
|
+
> [!NOTE]
|
|
112
|
+
> **Note:** To avoid a potential memory leak, pass in a `MutableContextWrapper` of your foreground `Activity` to the `getCredential()` call. Credential Manager handles updating the context during `Activity` reconstruction.
|
|
113
|
+
|
|
114
|
+
// Use an activity-based context to avoid undefined system UI
|
|
115
|
+
// launching behavior.
|
|
116
|
+
val context = MutableContextWrapper(activityContext)
|
|
117
|
+
coroutineScope {
|
|
118
|
+
try {
|
|
119
|
+
result = credentialManager.getCredential(
|
|
120
|
+
// Use MutableContextWrapper to avoid memory leak during configuration changes
|
|
121
|
+
context = context,
|
|
122
|
+
request = credentialRequest
|
|
123
|
+
)
|
|
124
|
+
handleSignIn(result)
|
|
125
|
+
} catch (e: GetCredentialException) {
|
|
126
|
+
// Handle failure
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
> [!NOTE]
|
|
131
|
+
> **Note:** If you call `getCredential()` but the user does not have any credentials available, or if they don't grant consent to using their credentials, a `NoCredentialException` is returned. To learn more about this exception, see the [troubleshooting guide](https://developer.android.com/identity/sign-in/credential-manager-troubleshooting-guide).
|
|
132
|
+
|
|
133
|
+
## Handle the response
|
|
134
|
+
|
|
135
|
+
Handle the response, which can contain one of various types of credential
|
|
136
|
+
objects.
|
|
137
|
+
|
|
138
|
+
fun handleSignIn(result: GetCredentialResponse) {
|
|
139
|
+
// Handle the successfully returned credential.
|
|
140
|
+
val credential = result.credential
|
|
141
|
+
|
|
142
|
+
when (credential) {
|
|
143
|
+
is PublicKeyCredential -> {
|
|
144
|
+
val responseJson = credential.authenticationResponseJson
|
|
145
|
+
// Share responseJson i.e. a GetCredentialResponse on your server to
|
|
146
|
+
// validate and authenticate
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
is PasswordCredential -> {
|
|
150
|
+
val username = credential.id
|
|
151
|
+
val password = credential.password
|
|
152
|
+
// Use id and password to send to your server to validate
|
|
153
|
+
// and authenticate
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
is CustomCredential -> {
|
|
157
|
+
// If you are also using any external sign-in libraries, parse them
|
|
158
|
+
// here with the utility functions provided.
|
|
159
|
+
if (credential.type == ExampleCustomCredential.TYPE) {
|
|
160
|
+
try {
|
|
161
|
+
val ExampleCustomCredential =
|
|
162
|
+
ExampleCustomCredential.createFrom(credential.data)
|
|
163
|
+
// Extract the required credentials and complete the authentication as per
|
|
164
|
+
// the federated sign in or any external sign in library flow
|
|
165
|
+
} catch (e: ExampleCustomCredential.ExampleCustomCredentialParsingException) {
|
|
166
|
+
// Unlikely to happen. If it does, you likely need to update the dependency
|
|
167
|
+
// version of your external sign-in library.
|
|
168
|
+
Log.e(TAG, "Failed to parse an ExampleCustomCredential", e)
|
|
169
|
+
}
|
|
170
|
+
} else {
|
|
171
|
+
// Catch any unrecognized custom credential type here.
|
|
172
|
+
Log.e(TAG, "Unexpected type of credential")
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else -> {
|
|
176
|
+
// Catch any unrecognized credential type here.
|
|
177
|
+
Log.e(TAG, "Unexpected type of credential")
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
The `PublicKeyCredential` returned from authentication is essentially a signed
|
|
183
|
+
assertion, structured as follows:
|
|
184
|
+
|
|
185
|
+
{
|
|
186
|
+
"id": "<credential ID>",
|
|
187
|
+
"type": "public-key",
|
|
188
|
+
"rawId": "<raw credential ID>",
|
|
189
|
+
"response": {
|
|
190
|
+
"clientDataJSON": "<signed client data containing challenge>",
|
|
191
|
+
"authenticatorData": "<authenticator metadata>",
|
|
192
|
+
"signature": "<digital signature to be verified>",
|
|
193
|
+
"userHandle": "<user ID from credential registration>"
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
On the server, you must verify the credential. To learn more, see [Verify and
|
|
198
|
+
sign in the user](https://developers.google.com/identity/passkeys/developer-guides/server-authentication#verify_and_sign_in_the_user).
|
|
199
|
+
|
|
200
|
+
## Handle exceptions
|
|
201
|
+
|
|
202
|
+
You should handle all the subclass exceptions of [`GetCredentialException`](https://developer.android.com/reference/androidx/credentials/exceptions/GetCredentialException).
|
|
203
|
+
To learn how to handle each exception, see the [troubleshooting guide](https://developer.android.com/identity/sign-in/credential-manager-troubleshooting-guide).
|
|
204
|
+
|
|
205
|
+
coroutineScope {
|
|
206
|
+
try {
|
|
207
|
+
result = credentialManager.getCredential(
|
|
208
|
+
context = activityContext,
|
|
209
|
+
request = credentialRequest
|
|
210
|
+
)
|
|
211
|
+
} catch (e: GetCredentialException) {
|
|
212
|
+
Log.e("CredentialManager", "No credential available", e)
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
## Next steps
|
|
217
|
+
|
|
218
|
+
- [Manage passkeys](https://developer.android.com/identity/passkeys/manage-passkeys)
|
|
219
|
+
- [Understand passkey user experience flows](https://developer.android.com/design/ui/mobile/guides/patterns/passkeys)
|