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.
Files changed (463) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +24 -0
  4. package/README.md +175 -168
  5. package/THIRD_PARTY_NOTICES.md +224 -4
  6. package/agents/android-architect.md +89 -0
  7. package/agents/android-performance-engineer.md +92 -0
  8. package/agents/android-test-engineer.md +97 -0
  9. package/agents/flutter-test-engineer.md +2 -0
  10. package/agents/ios-architect.md +93 -0
  11. package/agents/ios-performance-engineer.md +92 -0
  12. package/agents/ios-test-engineer.md +95 -0
  13. package/agents/lead-mobile.md +10 -1
  14. package/agents/mobile-staff-engineer.md +1 -1
  15. package/agents/rn-architect.md +94 -0
  16. package/agents/rn-performance-engineer.md +92 -0
  17. package/agents/rn-test-engineer.md +98 -0
  18. package/bin/reis-mobile.mjs +59 -17
  19. package/commands/debate.md +10 -1
  20. package/commands/debug.md +60 -0
  21. package/commands/reis-mobile.md +7 -2
  22. package/core/config/project.mjs +59 -0
  23. package/core/registry/frontmatter.mjs +15 -4
  24. package/core/registry/registry.mjs +21 -1
  25. package/core/router/intents.mjs +2 -0
  26. package/core/router/router.mjs +10 -5
  27. package/package.json +1 -1
  28. package/skills/android-adaptive/SKILL.md +304 -0
  29. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/flexbox/container-behavior.md +112 -0
  30. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/flexbox/get-started.md +69 -0
  31. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/flexbox/index.md +81 -0
  32. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/flexbox/item-behavior.md +170 -0
  33. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/container-properties.md +415 -0
  34. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/get-started.md +51 -0
  35. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/index.md +73 -0
  36. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/item-properties.md +170 -0
  37. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/mediaquery/index.md +333 -0
  38. package/skills/android-adaptive/references/android/develop/ui/compose/tooling/debug.md +114 -0
  39. package/skills/android-adaptive/references/android/guide/navigation/navigation-3/recipes/material-listdetail.md +141 -0
  40. package/skills/android-agp-9-upgrade/SKILL.md +106 -0
  41. package/skills/android-agp-9-upgrade/references/android/build/migrate-to-built-in-kotlin.md +416 -0
  42. package/skills/android-agp-9-upgrade/references/android/build/releases/agp-9-0-0-release-notes.md +554 -0
  43. package/skills/android-agp-9-upgrade/references/buildconfig.md +54 -0
  44. package/skills/android-agp-9-upgrade/references/ksp-kapt.md +39 -0
  45. package/skills/android-agp-9-upgrade/references/paparazzi-gradle-9.md +30 -0
  46. package/skills/android-agp-9-upgrade/references/recipes.md +62 -0
  47. package/skills/android-appfunctions/SKILL.md +74 -0
  48. package/skills/android-appfunctions/references/adb-interaction-testing.md +95 -0
  49. package/skills/android-appfunctions/references/context.md +26 -0
  50. package/skills/android-appfunctions/references/feature-discovery-analysis.md +71 -0
  51. package/skills/android-appfunctions/references/implementation-configuration.md +282 -0
  52. package/skills/android-appfunctions/references/kdoc-refinement-optimization.md +75 -0
  53. package/skills/android-appfunctions/references/migrate-to-service-entry-point.md +226 -0
  54. package/skills/android-camerax/SKILL.md +135 -0
  55. package/skills/android-camerax/references/camera1-to-camerax.md +198 -0
  56. package/skills/android-camerax/references/camera2-to-camerax.md +193 -0
  57. package/skills/android-camerax/references/expert-blueprints.md +58 -0
  58. package/skills/android-camerax/references/foldables.md +83 -0
  59. package/skills/android-camerax/references/immutability.md +60 -0
  60. package/skills/android-camerax/references/low-light.md +124 -0
  61. package/skills/android-camerax/references/mlkit-spatial.md +75 -0
  62. package/skills/android-camerax/references/modern-apis.md +42 -0
  63. package/skills/android-camerax/references/testing.md +69 -0
  64. package/skills/android-camerax/references/thermals.md +85 -0
  65. package/skills/android-camerax/references/wear-os.md +76 -0
  66. package/skills/android-camerax/references/xr.md +54 -0
  67. package/skills/android-cli/SKILL.md +474 -0
  68. package/skills/android-cli/references/interact.md +113 -0
  69. package/skills/android-cli/references/journeys.md +120 -0
  70. package/skills/android-code-review/SKILL.md +58 -0
  71. package/skills/android-display-glasses-with-jetpack-compose-glimmer/SKILL.md +340 -0
  72. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/design/ui/ai-glasses/guides/interaction/inputs.md +67 -0
  73. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/access-hardware-projected-context.md +388 -0
  74. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/buttons.md +139 -0
  75. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/cards.md +148 -0
  76. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/focus.md +107 -0
  77. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/icons.md +90 -0
  78. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/text.md +69 -0
  79. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/title-chips.md +82 -0
  80. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/request-hardware-permissions.md +213 -0
  81. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/button-samples-source.md +176 -0
  82. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/button-source.md +203 -0
  83. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/card-samples-source.md +296 -0
  84. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/card-source.md +515 -0
  85. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/deptheffect-source.md +224 -0
  86. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/deptheffectlevels-source.md +105 -0
  87. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/glimmersansflextypography-source.md +270 -0
  88. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/glimmertheme-source.md +182 -0
  89. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/icon-source.md +388 -0
  90. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/iconbutton-source.md +126 -0
  91. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/iconsizes-source.md +78 -0
  92. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/list-source.md +27 -0
  93. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/listitem-source.md +272 -0
  94. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/liststate-source.md +427 -0
  95. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/material-hct-source.md +217 -0
  96. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/projectedcontext-source.md +265 -0
  97. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/stack-source.md +368 -0
  98. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/stackitemscope-source.md +440 -0
  99. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/stackstate-source.md +325 -0
  100. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/surface-source.md +1211 -0
  101. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/titlechip-samples-source.md +101 -0
  102. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/titlechip-source.md +131 -0
  103. package/skills/android-edge-to-edge/SKILL.md +429 -0
  104. package/skills/android-engage-sdk-integration/SKILL.md +130 -0
  105. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/faq.md +439 -0
  106. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/food.md +1149 -0
  107. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/healthandfitness.md +1055 -0
  108. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/listen.md +1050 -0
  109. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/otherverticals.md +1301 -0
  110. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/read.md +910 -0
  111. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/shopping.md +1224 -0
  112. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/social.md +719 -0
  113. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/travel.md +1413 -0
  114. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/tv/continue-watching/index.md +19 -0
  115. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/tv/entitlements.md +353 -0
  116. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/tv/getting-started.md +202 -0
  117. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/tv/recommendations.md +471 -0
  118. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/watch.md +1081 -0
  119. package/skills/android-engage-sdk-integration/references/clusters.md +154 -0
  120. package/skills/android-engage-sdk-integration/references/common.md +519 -0
  121. package/skills/android-engage-sdk-integration/references/patterns.md +527 -0
  122. package/skills/android-engage-sdk-integration/references/requests.md +260 -0
  123. package/skills/android-engage-sdk-integration/references/schemas/food.md +509 -0
  124. package/skills/android-engage-sdk-integration/references/schemas/listen.md +842 -0
  125. package/skills/android-engage-sdk-integration/references/schemas/other.md +220 -0
  126. package/skills/android-engage-sdk-integration/references/schemas/read.md +412 -0
  127. package/skills/android-engage-sdk-integration/references/schemas/shopping.md +357 -0
  128. package/skills/android-engage-sdk-integration/references/schemas/social.md +228 -0
  129. package/skills/android-engage-sdk-integration/references/schemas/travel.md +923 -0
  130. package/skills/android-engage-sdk-integration/references/schemas/tv.md +1226 -0
  131. package/skills/android-engage-sdk-integration/references/schemas/watch.md +1137 -0
  132. package/skills/android-engage-sdk-integration/references/troubleshooting.md +39 -0
  133. package/skills/android-gradle-build-debug/SKILL.md +71 -0
  134. package/skills/android-intent-security/SKILL.md +550 -0
  135. package/skills/android-leanback-to-compose-tv-migration/SKILL.md +743 -0
  136. package/skills/android-leanback-to-compose-tv-migration/references/android/training/tv/get-started/navigation.md +372 -0
  137. package/skills/android-leanback-to-compose-tv-migration/references/android/training/tv/playback/compose/browse.md +243 -0
  138. package/skills/android-leanback-to-compose-tv-migration/references/android/training/tv/playback/compose/index.md +153 -0
  139. package/skills/android-media3-cast-integration/SKILL.md +236 -0
  140. package/skills/android-media3-cast-integration/references/android/media/media3/cast/create-castplayer.md +390 -0
  141. package/skills/android-media3-cast-integration/references/android/media/media3/cast/customize-castoptions.md +93 -0
  142. package/skills/android-media3-cast-integration/references/android/media/media3/cast/index.md +21 -0
  143. package/skills/android-migrate-xml-views-to-jetpack-compose/SKILL.md +127 -0
  144. package/skills/android-migrate-xml-views-to-jetpack-compose/references/analysis-of-the-project-and-layout.md +42 -0
  145. package/skills/android-migrate-xml-views-to-jetpack-compose/references/android/develop/ui/compose/designsystems/migrate-xml-theme-to-compose.md +171 -0
  146. package/skills/android-migrate-xml-views-to-jetpack-compose/references/android/develop/ui/compose/migrate/interoperability-apis/compose-in-views.md +299 -0
  147. package/skills/android-migrate-xml-views-to-jetpack-compose/references/android/develop/ui/compose/migrate/interoperability-apis/views-in-compose.md +286 -0
  148. package/skills/android-migrate-xml-views-to-jetpack-compose/references/android/develop/ui/compose/setup-compose-dependencies-and-compiler.md +197 -0
  149. package/skills/android-migrate-xml-views-to-jetpack-compose/references/identify-optimal-xml-candidate.md +31 -0
  150. package/skills/android-migrate-xml-views-to-jetpack-compose/references/xml-layout-migration.md +86 -0
  151. package/skills/android-ml-kit-genai-prompt-api/SKILL.md +124 -0
  152. package/skills/android-ml-kit-genai-prompt-api/references/get-started.md +272 -0
  153. package/skills/android-ml-kit-genai-prompt-api/references/prefix-caching.md +146 -0
  154. package/skills/android-ml-kit-genai-prompt-api/references/prompt-design.md +55 -0
  155. package/skills/android-ml-kit-genai-prompt-api/references/prompt-optimization.md +74 -0
  156. package/skills/android-ml-kit-genai-prompt-api/references/structured-output.md +219 -0
  157. package/skills/android-ml-kit-genai-prompt-api/references/system-instructions.md +71 -0
  158. package/skills/android-navigation-3/SKILL.md +122 -0
  159. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/index.md +51 -0
  160. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/migration-guide.md +670 -0
  161. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/animations.md +147 -0
  162. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/basic.md +89 -0
  163. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/basicdsl.md +85 -0
  164. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/basicsaveable.md +90 -0
  165. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/bottomsheet.md +195 -0
  166. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/common-ui.md +200 -0
  167. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/conditional-transitions.md +182 -0
  168. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/conditional.md +230 -0
  169. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/deeplinks-custommatcher.md +176 -0
  170. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/deeplinks-staticuri.md +140 -0
  171. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/deeplinks-syntheticbackstack.md +184 -0
  172. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/dialog.md +107 -0
  173. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/lifecycle-owner.md +185 -0
  174. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/material-listdetail.md +141 -0
  175. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/material-supportingpane.md +145 -0
  176. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/modular-hilt.md +283 -0
  177. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/modular-koin.md +287 -0
  178. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/multiple-backstacks.md +468 -0
  179. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/passingarguments.md +371 -0
  180. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/results-event.md +273 -0
  181. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/results-state.md +266 -0
  182. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/scenes-listdetail.md +435 -0
  183. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/scenes-twopane.md +244 -0
  184. package/skills/android-navigation-3/references/android/guide/navigation/type-safe-destinations.md +129 -0
  185. package/skills/android-navigation-event/SKILL.md +312 -0
  186. package/skills/android-navigation-event/references/android/guide/navigation/navigation-event/dispatcher.md +134 -0
  187. package/skills/android-navigation-event/references/android/guide/navigation/navigation-event/handle-back.md +217 -0
  188. package/skills/android-navigation-event/references/android/guide/navigation/navigation-event/index.md +83 -0
  189. package/skills/android-navigation-event/references/android/guide/navigation/navigation-event/setup.md +32 -0
  190. package/skills/android-play-billing-library-version-upgrade/SKILL.md +96 -0
  191. package/skills/android-play-billing-library-version-upgrade/references/android/google/play/billing/release-notes.md +1240 -0
  192. package/skills/android-play-billing-library-version-upgrade/references/migration-logic.md +78 -0
  193. package/skills/android-play-billing-library-version-upgrade/references/version-checklist.md +54 -0
  194. package/skills/android-play-policy-insights/SKILL.md +172 -0
  195. package/skills/android-play-policy-insights/resources/common_mandates.md +100 -0
  196. package/skills/android-play-policy-insights/resources/compliance_report_template.md +59 -0
  197. package/skills/android-play-policy-insights/resources/critic.md +86 -0
  198. package/skills/android-play-policy-insights/resources/goal_data_safety.md +212 -0
  199. package/skills/android-play-policy-insights/resources/goal_permissions_and_apis.md +459 -0
  200. package/skills/android-play-policy-insights/resources/goal_user_account.md +106 -0
  201. package/skills/android-play-policy-insights/resources/policies.json +321 -0
  202. package/skills/android-play-policy-insights/resources/scanner_config.json +843 -0
  203. package/skills/android-play-policy-insights/scripts/generate_report.py +860 -0
  204. package/skills/android-play-policy-insights/scripts/orchestrator.py +1313 -0
  205. package/skills/android-play-policy-insights/scripts/play_store_scraper.py +410 -0
  206. package/skills/android-play-policy-insights/scripts/scanner.py +261 -0
  207. package/skills/android-play-policy-insights/scripts/template_engine.py +243 -0
  208. package/skills/android-profiler/SKILL.md +60 -0
  209. package/skills/android-profiler/analysis/analysis_orchestrator.md +32 -0
  210. package/skills/android-profiler/analysis/workflows/perfetto-sql/perfetto_sql.md +28 -0
  211. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/perfetto_trace_analysis.md +121 -0
  212. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/guiding_principles.md +51 -0
  213. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/domain_hints_template.md +7 -0
  214. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_cpu.md +56 -0
  215. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_graphics.md +51 -0
  216. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_io.md +46 -0
  217. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_ipc.md +41 -0
  218. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_memory.md +55 -0
  219. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_power.md +33 -0
  220. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/per_candidate_analysis.md +172 -0
  221. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/triage.md +94 -0
  222. package/skills/android-profiler/recording/recording_orchestrator.md +36 -0
  223. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/perfetto_trace_recording.md +148 -0
  224. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/app_jank.pftxt +43 -0
  225. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/cpu_profile.pftxt +35 -0
  226. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/java_heap_dump.pftxt +21 -0
  227. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/long_background.pftxt +37 -0
  228. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/memory_counters.pftxt +45 -0
  229. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/native_heap.pftxt +21 -0
  230. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/sched_cpu.pftxt +33 -0
  231. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/trace_config_reference.md +102 -0
  232. package/skills/android-profiler/references/env_setup.md +15 -0
  233. package/skills/android-profiler/references/perfetto/setup.md +29 -0
  234. package/skills/android-profiler/references/perfetto/sql.md +327 -0
  235. package/skills/android-r8-analyzer/SKILL.md +72 -0
  236. package/skills/android-r8-analyzer/references/CONFIGURATION-ANALYZER.md +287 -0
  237. package/skills/android-r8-analyzer/references/CONFIGURATION.md +44 -0
  238. package/skills/android-r8-analyzer/references/KEEP-RULES-IMPACT-HIERARCHY.md +83 -0
  239. package/skills/android-r8-analyzer/references/REDUNDANT-RULES.md +222 -0
  240. package/skills/android-r8-analyzer/references/REFLECTION-GUIDE.md +139 -0
  241. package/skills/android-r8-analyzer/references/REPORT_FORMAT.md +51 -0
  242. package/skills/android-r8-analyzer/references/android/topic/performance/app-optimization/enable-app-optimization.md +252 -0
  243. package/skills/android-r8-analyzer/references/android/training/testing/other-components/ui-automator.md +312 -0
  244. package/skills/android-restore-credentials/SKILL.md +359 -0
  245. package/skills/android-restore-credentials/references/android/guide/topics/manifest/application-element.md +832 -0
  246. package/skills/android-restore-credentials/references/android/identity/passkeys/create-passkeys.md +327 -0
  247. package/skills/android-restore-credentials/references/android/identity/passkeys/sign-in-with-passkeys.md +219 -0
  248. package/skills/android-styles/SKILL.md +229 -0
  249. package/skills/android-styles/references/android/develop/ui/compose/designsystems/custom.md +459 -0
  250. package/skills/android-styles/references/android/develop/ui/compose/styles/fundamentals.md +421 -0
  251. package/skills/android-styles/references/android/develop/ui/compose/styles/state-animations.md +461 -0
  252. package/skills/android-styles/references/android/develop/ui/compose/styles/styles-vs-modifiers.md +48 -0
  253. package/skills/android-styles/references/android/develop/ui/compose/styles/theming.md +269 -0
  254. package/skills/android-verified-email/SKILL.md +432 -0
  255. package/skills/android-verified-email/references/android/identity/credential-manager/index.md +67 -0
  256. package/skills/android-verified-email/references/android/identity/digital-credentials/credential-verifier.md +166 -0
  257. package/skills/android-verified-email/references/android/identity/digital-credentials/email-verification-implementation.md +313 -0
  258. package/skills/android-verified-email/references/android/identity/digital-credentials/email-verification.md +158 -0
  259. package/skills/android-verified-email/references/android/identity/digital-credentials/index.md +112 -0
  260. package/skills/android-verified-email/references/android/identity/passkeys/create-passkeys.md +327 -0
  261. package/skills/android-verified-email/references/android/identity/sign-in/credential-manager-webview.md +84 -0
  262. package/skills/android-wear-compose-m3/SKILL.md +365 -0
  263. package/skills/android-wear-compose-m3/references/android/training/wearables/compose/migrate-to-material3.md +677 -0
  264. package/skills/android-wear-compose-m3/references/foundation/AmbientModeSample.kt.md +123 -0
  265. package/skills/android-wear-compose-m3/references/foundation/AmbientModeSample.kt.md.txt +123 -0
  266. package/skills/android-wear-compose-m3/references/foundation/CurvedWorldSample.kt.md +430 -0
  267. package/skills/android-wear-compose-m3/references/foundation/CurvedWorldSample.kt.md.txt +430 -0
  268. package/skills/android-wear-compose-m3/references/foundation/ExpandableSample.kt.md +99 -0
  269. package/skills/android-wear-compose-m3/references/foundation/ExpandableSample.kt.md.txt +99 -0
  270. package/skills/android-wear-compose-m3/references/foundation/HierarchicalFocusSample.kt.md +141 -0
  271. package/skills/android-wear-compose-m3/references/foundation/HierarchicalFocusSample.kt.md.txt +141 -0
  272. package/skills/android-wear-compose-m3/references/foundation/PagerSamples.kt.md +56 -0
  273. package/skills/android-wear-compose-m3/references/foundation/PagerSamples.kt.md.txt +56 -0
  274. package/skills/android-wear-compose-m3/references/foundation/RotarySamples.kt.md +153 -0
  275. package/skills/android-wear-compose-m3/references/foundation/RotarySamples.kt.md.txt +153 -0
  276. package/skills/android-wear-compose-m3/references/foundation/ScalingLazyColumnSample.kt.md +131 -0
  277. package/skills/android-wear-compose-m3/references/foundation/ScalingLazyColumnSample.kt.md.txt +131 -0
  278. package/skills/android-wear-compose-m3/references/foundation/SwipeToDismissBoxSample.kt.md +169 -0
  279. package/skills/android-wear-compose-m3/references/foundation/SwipeToDismissBoxSample.kt.md.txt +169 -0
  280. package/skills/android-wear-compose-m3/references/foundation/SwipeToRevealSample.kt.md +282 -0
  281. package/skills/android-wear-compose-m3/references/foundation/SwipeToRevealSample.kt.md.txt +282 -0
  282. package/skills/android-wear-compose-m3/references/foundation/TransformingLazyColumnSample.kt.md +335 -0
  283. package/skills/android-wear-compose-m3/references/foundation/TransformingLazyColumnSample.kt.md.txt +335 -0
  284. package/skills/android-wear-compose-m3/references/material3/AlertDialogSample.kt.md +377 -0
  285. package/skills/android-wear-compose-m3/references/material3/AlertDialogSample.kt.md.txt +377 -0
  286. package/skills/android-wear-compose-m3/references/material3/AnimatedTextSample.kt.md +165 -0
  287. package/skills/android-wear-compose-m3/references/material3/AnimatedTextSample.kt.md.txt +165 -0
  288. package/skills/android-wear-compose-m3/references/material3/ButtonGroupSample.kt.md +91 -0
  289. package/skills/android-wear-compose-m3/references/material3/ButtonGroupSample.kt.md.txt +91 -0
  290. package/skills/android-wear-compose-m3/references/material3/ButtonSample.kt.md +496 -0
  291. package/skills/android-wear-compose-m3/references/material3/ButtonSample.kt.md.txt +496 -0
  292. package/skills/android-wear-compose-m3/references/material3/CardSample.kt.md +470 -0
  293. package/skills/android-wear-compose-m3/references/material3/CardSample.kt.md.txt +470 -0
  294. package/skills/android-wear-compose-m3/references/material3/CheckboxButtonSample.kt.md +67 -0
  295. package/skills/android-wear-compose-m3/references/material3/CheckboxButtonSample.kt.md.txt +67 -0
  296. package/skills/android-wear-compose-m3/references/material3/ConfirmationDialogSample.kt.md +162 -0
  297. package/skills/android-wear-compose-m3/references/material3/ConfirmationDialogSample.kt.md.txt +162 -0
  298. package/skills/android-wear-compose-m3/references/material3/CurvedTextSamples.kt.md +78 -0
  299. package/skills/android-wear-compose-m3/references/material3/CurvedTextSamples.kt.md.txt +78 -0
  300. package/skills/android-wear-compose-m3/references/material3/DatePickerSample.kt.md +131 -0
  301. package/skills/android-wear-compose-m3/references/material3/DatePickerSample.kt.md.txt +131 -0
  302. package/skills/android-wear-compose-m3/references/material3/DynamicColorSchemeSample.kt.md +74 -0
  303. package/skills/android-wear-compose-m3/references/material3/DynamicColorSchemeSample.kt.md.txt +74 -0
  304. package/skills/android-wear-compose-m3/references/material3/EdgeButtonSample.kt.md +63 -0
  305. package/skills/android-wear-compose-m3/references/material3/EdgeButtonSample.kt.md.txt +63 -0
  306. package/skills/android-wear-compose-m3/references/material3/FadingExpandingLabelSample.kt.md +60 -0
  307. package/skills/android-wear-compose-m3/references/material3/FadingExpandingLabelSample.kt.md.txt +60 -0
  308. package/skills/android-wear-compose-m3/references/material3/IconButtonSample.kt.md +125 -0
  309. package/skills/android-wear-compose-m3/references/material3/IconButtonSample.kt.md.txt +125 -0
  310. package/skills/android-wear-compose-m3/references/material3/IconToggleButtonSample.kt.md +116 -0
  311. package/skills/android-wear-compose-m3/references/material3/IconToggleButtonSample.kt.md.txt +116 -0
  312. package/skills/android-wear-compose-m3/references/material3/LevelIndicatorSample.kt.md +68 -0
  313. package/skills/android-wear-compose-m3/references/material3/LevelIndicatorSample.kt.md.txt +68 -0
  314. package/skills/android-wear-compose-m3/references/material3/LinearProgressIndicatorSample.kt.md +50 -0
  315. package/skills/android-wear-compose-m3/references/material3/LinearProgressIndicatorSample.kt.md.txt +50 -0
  316. package/skills/android-wear-compose-m3/references/material3/ListHeaderSample.kt.md +177 -0
  317. package/skills/android-wear-compose-m3/references/material3/ListHeaderSample.kt.md.txt +177 -0
  318. package/skills/android-wear-compose-m3/references/material3/OneHandedGestureSamples.kt.md +651 -0
  319. package/skills/android-wear-compose-m3/references/material3/OneHandedGestureSamples.kt.md.txt +651 -0
  320. package/skills/android-wear-compose-m3/references/material3/OpenOnPhoneDialogSample.kt.md +57 -0
  321. package/skills/android-wear-compose-m3/references/material3/OpenOnPhoneDialogSample.kt.md.txt +57 -0
  322. package/skills/android-wear-compose-m3/references/material3/PageIndicatorSample.kt.md +110 -0
  323. package/skills/android-wear-compose-m3/references/material3/PageIndicatorSample.kt.md.txt +110 -0
  324. package/skills/android-wear-compose-m3/references/material3/PagerScaffoldSample.kt.md +204 -0
  325. package/skills/android-wear-compose-m3/references/material3/PagerScaffoldSample.kt.md.txt +204 -0
  326. package/skills/android-wear-compose-m3/references/material3/PickerGroupSample.kt.md +139 -0
  327. package/skills/android-wear-compose-m3/references/material3/PickerGroupSample.kt.md.txt +139 -0
  328. package/skills/android-wear-compose-m3/references/material3/PickerSample.kt.md +111 -0
  329. package/skills/android-wear-compose-m3/references/material3/PickerSample.kt.md.txt +111 -0
  330. package/skills/android-wear-compose-m3/references/material3/PlaceholderSample.kt.md +184 -0
  331. package/skills/android-wear-compose-m3/references/material3/PlaceholderSample.kt.md.txt +184 -0
  332. package/skills/android-wear-compose-m3/references/material3/ProgressIndicatorSample.kt.md +263 -0
  333. package/skills/android-wear-compose-m3/references/material3/ProgressIndicatorSample.kt.md.txt +263 -0
  334. package/skills/android-wear-compose-m3/references/material3/RadioButtonSample.kt.md +105 -0
  335. package/skills/android-wear-compose-m3/references/material3/RadioButtonSample.kt.md.txt +105 -0
  336. package/skills/android-wear-compose-m3/references/material3/ScaffoldSample.kt.md +146 -0
  337. package/skills/android-wear-compose-m3/references/material3/ScaffoldSample.kt.md.txt +146 -0
  338. package/skills/android-wear-compose-m3/references/material3/ScrollAwaySample.kt.md +97 -0
  339. package/skills/android-wear-compose-m3/references/material3/ScrollAwaySample.kt.md.txt +97 -0
  340. package/skills/android-wear-compose-m3/references/material3/ScrollIndicatorSample.kt.md +66 -0
  341. package/skills/android-wear-compose-m3/references/material3/ScrollIndicatorSample.kt.md.txt +66 -0
  342. package/skills/android-wear-compose-m3/references/material3/SliderSample.kt.md +86 -0
  343. package/skills/android-wear-compose-m3/references/material3/SliderSample.kt.md.txt +86 -0
  344. package/skills/android-wear-compose-m3/references/material3/StepperSample.kt.md +148 -0
  345. package/skills/android-wear-compose-m3/references/material3/StepperSample.kt.md.txt +148 -0
  346. package/skills/android-wear-compose-m3/references/material3/SurfaceTransformationSample.kt.md +166 -0
  347. package/skills/android-wear-compose-m3/references/material3/SurfaceTransformationSample.kt.md.txt +166 -0
  348. package/skills/android-wear-compose-m3/references/material3/SwipeToDismissBoxSample.kt.md +172 -0
  349. package/skills/android-wear-compose-m3/references/material3/SwipeToDismissBoxSample.kt.md.txt +172 -0
  350. package/skills/android-wear-compose-m3/references/material3/SwipeToRevealSample.kt.md +367 -0
  351. package/skills/android-wear-compose-m3/references/material3/SwipeToRevealSample.kt.md.txt +367 -0
  352. package/skills/android-wear-compose-m3/references/material3/SwitchButtonSample.kt.md +66 -0
  353. package/skills/android-wear-compose-m3/references/material3/SwitchButtonSample.kt.md.txt +66 -0
  354. package/skills/android-wear-compose-m3/references/material3/TextButtonSample.kt.md +115 -0
  355. package/skills/android-wear-compose-m3/references/material3/TextButtonSample.kt.md.txt +115 -0
  356. package/skills/android-wear-compose-m3/references/material3/TextToggleButtonSample.kt.md +71 -0
  357. package/skills/android-wear-compose-m3/references/material3/TextToggleButtonSample.kt.md.txt +71 -0
  358. package/skills/android-wear-compose-m3/references/material3/TimePickerSample.kt.md +151 -0
  359. package/skills/android-wear-compose-m3/references/material3/TimePickerSample.kt.md.txt +151 -0
  360. package/skills/android-wear-compose-m3/references/material3/TimeTextSample.kt.md +65 -0
  361. package/skills/android-wear-compose-m3/references/material3/TimeTextSample.kt.md.txt +65 -0
  362. package/skills/android-wear-compose-m3/references/material3/TransformationSpecSample.kt.md +246 -0
  363. package/skills/android-wear-compose-m3/references/material3/TransformationSpecSample.kt.md.txt +246 -0
  364. package/skills/android-wear-compose-m3/references/material3/TransformingLazyColumnNotificationsSample.kt.md +89 -0
  365. package/skills/android-wear-compose-m3/references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt +89 -0
  366. package/skills/android-wear-compose-m3/references/material3/TransformingLazyColumnSample.kt.md +309 -0
  367. package/skills/android-wear-compose-m3/references/material3/TransformingLazyColumnSample.kt.md.txt +309 -0
  368. package/skills/android-wear-compose-m3/references/navigation3/SwipeDismissableSceneStrategySample.kt.md +205 -0
  369. package/skills/android-wear-compose-m3/references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt +205 -0
  370. package/skills/{architecture-feature-first → flutter-architecture-feature-first}/SKILL.md +1 -1
  371. package/skills/{bloc → flutter-bloc}/SKILL.md +1 -1
  372. package/skills/flutter-build-debug/SKILL.md +66 -0
  373. package/skills/{code-review → flutter-code-review}/SKILL.md +1 -1
  374. package/skills/{dart-3-updates → flutter-dart-3-updates}/SKILL.md +1 -1
  375. package/skills/{dart-fix-runtime-errors → flutter-dart-fix-runtime-errors}/SKILL.md +1 -1
  376. package/skills/{dart-resolve-package-conflicts → flutter-dart-resolve-package-conflicts}/SKILL.md +1 -1
  377. package/skills/{dart-run-static-analysis → flutter-dart-run-static-analysis}/SKILL.md +1 -1
  378. package/skills/{dart-use-pattern-matching → flutter-dart-use-pattern-matching}/SKILL.md +1 -1
  379. package/skills/{effective-dart → flutter-effective-dart}/SKILL.md +1 -1
  380. package/skills/{provider → flutter-provider}/SKILL.md +1 -1
  381. package/skills/{riverpod → flutter-riverpod}/SKILL.md +1 -1
  382. package/skills/ios-cocoapods-debug/SKILL.md +65 -0
  383. package/skills/ios-code-review/SKILL.md +56 -0
  384. package/skills/ios-xcode-build-debug/SKILL.md +66 -0
  385. package/skills/{detect-mobile-stack → mobile-detect-stack}/SKILL.md +1 -1
  386. package/skills/mobile-firebase/SKILL.md +54 -0
  387. package/skills/mobile-firebase/references/android/ai-logic.md +31 -0
  388. package/skills/mobile-firebase/references/android/analytics.md +33 -0
  389. package/skills/mobile-firebase/references/android/app-check.md +36 -0
  390. package/skills/mobile-firebase/references/android/auth.md +44 -0
  391. package/skills/mobile-firebase/references/android/crashlytics.md +31 -0
  392. package/skills/mobile-firebase/references/android/firestore.md +44 -0
  393. package/skills/mobile-firebase/references/android/functions.md +33 -0
  394. package/skills/mobile-firebase/references/android/in-app-messaging.md +28 -0
  395. package/skills/mobile-firebase/references/android/messaging.md +41 -0
  396. package/skills/mobile-firebase/references/android/realtime-database.md +50 -0
  397. package/skills/mobile-firebase/references/android/remote-config.md +43 -0
  398. package/skills/mobile-firebase/references/android/sql-connect.md +31 -0
  399. package/skills/mobile-firebase/references/android/storage.md +39 -0
  400. package/skills/mobile-firebase/references/android.md +30 -0
  401. package/skills/{firebase-ai/SKILL.md → mobile-firebase/references/flutter/ai-logic.md} +2 -8
  402. package/skills/{firebase-analytics/SKILL.md → mobile-firebase/references/flutter/analytics.md} +2 -8
  403. package/skills/{firebase-app-check/SKILL.md → mobile-firebase/references/flutter/app-check.md} +2 -8
  404. package/skills/{firebase-auth/SKILL.md → mobile-firebase/references/flutter/auth.md} +2 -8
  405. package/skills/{firebase-crashlytics/SKILL.md → mobile-firebase/references/flutter/crashlytics.md} +2 -8
  406. package/skills/{firebase-cloud-firestore/SKILL.md → mobile-firebase/references/flutter/firestore.md} +2 -8
  407. package/skills/{firebase-cloud-functions/SKILL.md → mobile-firebase/references/flutter/functions.md} +2 -8
  408. package/skills/{firebase-in-app-messaging/SKILL.md → mobile-firebase/references/flutter/in-app-messaging.md} +2 -8
  409. package/skills/{firebase-messaging/SKILL.md → mobile-firebase/references/flutter/messaging.md} +2 -8
  410. package/skills/{firebase-database/SKILL.md → mobile-firebase/references/flutter/realtime-database.md} +2 -8
  411. package/skills/{firebase-remote-config/SKILL.md → mobile-firebase/references/flutter/remote-config.md} +2 -8
  412. package/skills/{flutterfire-configure/SKILL.md → mobile-firebase/references/flutter/setup-flutterfire.md} +1 -8
  413. package/skills/{firebase-data-connect/SKILL.md → mobile-firebase/references/flutter/sql-connect.md} +2 -8
  414. package/skills/{firebase-storage/SKILL.md → mobile-firebase/references/flutter/storage.md} +2 -8
  415. package/skills/mobile-firebase/references/flutter.md +36 -0
  416. package/skills/mobile-firebase/references/ios/ai-logic.md +30 -0
  417. package/skills/mobile-firebase/references/ios/analytics.md +33 -0
  418. package/skills/mobile-firebase/references/ios/app-check.md +36 -0
  419. package/skills/mobile-firebase/references/ios/auth.md +48 -0
  420. package/skills/mobile-firebase/references/ios/crashlytics.md +34 -0
  421. package/skills/mobile-firebase/references/ios/firestore.md +53 -0
  422. package/skills/mobile-firebase/references/ios/functions.md +35 -0
  423. package/skills/mobile-firebase/references/ios/in-app-messaging.md +26 -0
  424. package/skills/mobile-firebase/references/ios/messaging.md +45 -0
  425. package/skills/mobile-firebase/references/ios/realtime-database.md +49 -0
  426. package/skills/mobile-firebase/references/ios/remote-config.md +44 -0
  427. package/skills/mobile-firebase/references/ios/sql-connect.md +33 -0
  428. package/skills/mobile-firebase/references/ios/storage.md +36 -0
  429. package/skills/mobile-firebase/references/ios.md +28 -0
  430. package/skills/mobile-firebase/references/react-native/ai-logic.md +32 -0
  431. package/skills/mobile-firebase/references/react-native/analytics.md +43 -0
  432. package/skills/mobile-firebase/references/react-native/app-check.md +35 -0
  433. package/skills/mobile-firebase/references/react-native/auth.md +50 -0
  434. package/skills/mobile-firebase/references/react-native/crashlytics.md +36 -0
  435. package/skills/mobile-firebase/references/react-native/firestore.md +45 -0
  436. package/skills/mobile-firebase/references/react-native/functions.md +28 -0
  437. package/skills/mobile-firebase/references/react-native/in-app-messaging.md +27 -0
  438. package/skills/mobile-firebase/references/react-native/messaging.md +46 -0
  439. package/skills/mobile-firebase/references/react-native/realtime-database.md +46 -0
  440. package/skills/mobile-firebase/references/react-native/remote-config.md +32 -0
  441. package/skills/mobile-firebase/references/react-native/sql-connect.md +11 -0
  442. package/skills/mobile-firebase/references/react-native/storage.md +30 -0
  443. package/skills/mobile-firebase/references/react-native.md +29 -0
  444. package/skills/mobile-test/SKILL.md +63 -0
  445. package/skills/mobile-test/references/android/setup/GUIDE.md +183 -0
  446. package/skills/mobile-test/references/android/setup/references/android/develop/ui/compose/testing/common-patterns.md +181 -0
  447. package/skills/mobile-test/references/android/setup/references/android/studio/preview/compose-screenshot-testing.md +255 -0
  448. package/skills/mobile-test/references/android/setup/references/android/training/dependency-injection/hilt-testing.md +447 -0
  449. package/skills/mobile-test/references/android.md +83 -0
  450. package/skills/{dart-collect-coverage/SKILL.md → mobile-test/references/flutter/coverage.md} +2 -11
  451. package/skills/{dart-generate-test-mocks/SKILL.md → mobile-test/references/flutter/generate-mocks.md} +2 -11
  452. package/skills/{flutter-add-integration-test/SKILL.md → mobile-test/references/flutter/integration-tests.md} +2 -11
  453. package/skills/{dart-migrate-to-checks-package/SKILL.md → mobile-test/references/flutter/migrate-to-checks.md} +2 -13
  454. package/skills/{mockito/SKILL.md → mobile-test/references/flutter/mockito.md} +1 -8
  455. package/skills/{mocktail/SKILL.md → mobile-test/references/flutter/mocktail.md} +1 -8
  456. package/skills/{patrol-e2e-testing/SKILL.md → mobile-test/references/flutter/patrol.md} +1 -8
  457. package/skills/{testing/SKILL.md → mobile-test/references/flutter/testing-guidelines.md} +1 -8
  458. package/skills/{dart-add-unit-test/SKILL.md → mobile-test/references/flutter/unit-tests.md} +2 -11
  459. package/skills/{flutter-add-widget-test/SKILL.md → mobile-test/references/flutter/widget-tests.md} +2 -11
  460. package/skills/mobile-test/references/flutter.md +44 -0
  461. package/skills/mobile-test/references/ios.md +79 -0
  462. package/skills/mobile-test/references/react-native.md +62 -0
  463. /package/skills/{dart-use-pattern-matching → flutter-dart-use-pattern-matching}/examples/json_patterns.dart +0 -0
@@ -0,0 +1,1081 @@
1
+ > [!IMPORTANT]
2
+ > **Important:** Engage SDK has superseded Media Home, which is now deprecated. If you have an existing Media Home integration, follow the instructions in these guides to migrate your content to Engage SDK, which allows your content to be published to more devices and form factors. Please contact [`engage-developers@google.com`](mailto:engage-developers@google.com) if you have any questions.
3
+
4
+ Boost app engagement by reaching your users where they are. Integrate Engage
5
+ SDK to deliver Continue Watching content and personalized recommendations
6
+ directly to users across multiple on-device surfaces
7
+ **[Collections](https://android-developers.googleblog.com/2024/07/introducing-collections-powered-by-engage-sdk.html)** ,
8
+ **[Entertainment Space](https://blog.google/products/android/entertainment-space/)** , and the Play Store. The
9
+ integration adds less than 50 KB (compressed) to the average APK and takes
10
+ most apps about a week of developer time. Learn more at our
11
+ **[business site](http://play.google.com/console/about/programs/EngageSDK)**.
12
+
13
+ This guide contains instructions for developer partners to integrate their video
14
+ content, using the Engage SDK to populate both this new surface area and
15
+ existing Google surfaces.
16
+
17
+ > [!NOTE]
18
+ > **Note:** Check the [TV integration guide](https://developer.android.com/guide/playcore/engage/tv) to learn more about the Continue Watching experience on Google TV.
19
+
20
+ ## Integration detail
21
+
22
+ ### Terminology
23
+
24
+ This integration includes the following three cluster types: **Recommendation** ,
25
+ **Continuation** , and **Featured**.
26
+
27
+ - **Recommendation** clusters show personalized suggestions for content to watch
28
+ from an individual developer partner.
29
+
30
+ Your recommendations take the following structure:
31
+ - **Recommendation Cluster:** A UI view that contains a group of
32
+ recommendations from the same developer partner.
33
+
34
+ ![](https://developer.android.com/static/images/guide/playcore/engage/watch-term-1.png) **Figure 1.** Entertainment Space UI showing a Recommendation Cluster from a single partner.
35
+ - **Entity:** An object representing a single item in a cluster. An entity
36
+ can be a movie, a TV show, a TV series, live video, and more. See the
37
+ [Provide entity data](https://developer.android.com/guide/playcore/engage/watch#provide-entity-data) section for a list of
38
+ supported entity types.
39
+
40
+ ![](https://developer.android.com/static/images/guide/playcore/engage/watch-term-2.png) **Figure 2.** Entertainment Space UI showing a single Entity within a single partner's Recommendation Cluster.
41
+ - The **Continuation** cluster shows unfinished videos and relevant newly
42
+ released episodes from multiple developer partners in one UI grouping. Each
43
+ developer partner will be allowed to broadcast a maximum of 10 entities in the
44
+ Continuation cluster. Research has shown that personalized recommendations
45
+ along with personalized Continuation content creates the best user engagement.
46
+
47
+ ![](https://developer.android.com/static/images/guide/playcore/engage/watch-term-3.png) **Figure 3.** Entertainment Space UI showing a Continuation cluster with unfinished recommendations from multiple partners (only one recommendation is currently visible).
48
+ - The **Featured** cluster showcases a selection of entities from multiple
49
+ developer partners in one UI grouping. There will be a single Featured
50
+ cluster, which is surfaced near the top of the UI with a priority placement
51
+ above all Recommendation clusters. Each developer partner will be allowed to
52
+ broadcast up to 10 entities in the Featured cluster.
53
+
54
+ ![](https://developer.android.com/static/images/guide/playcore/engage/watch-term-4.png) **Figure 4.** Entertainment Space UI showing a Featured cluster with recommendations from multiple partners (only one recommendation is currently visible).
55
+
56
+ ### Pre-work
57
+
58
+ Minimum API level: 19
59
+
60
+ Add the `com.google.android.engage:engage-core` library to your app:
61
+
62
+ dependencies {
63
+ // Make sure you also include that repository in your project's build.gradle file.
64
+ implementation 'com.google.android.engage:engage-core:1.6.0'
65
+ }
66
+
67
+ For more information, see [Package visibility in Android
68
+ 11](https://developer.android.com/about/versions/11/privacy/package-visibility).
69
+
70
+ ### Summary
71
+
72
+ The design is based on an implementation of a [bound
73
+ service](https://developer.android.com/guide/components/bound-services).
74
+
75
+ The data a client can publish is subject to the following limits for different
76
+ cluster types:
77
+
78
+ | Cluster type | Cluster limits | Maximum entity limits in a cluster |
79
+ |---|---|---|
80
+ | Recommendation Cluster(s) | At most 7 | At most 50 |
81
+ | Continuation Cluster | At most 1 | At most 20 |
82
+ | Featured Cluster | At most 1 | At most 20 |
83
+
84
+ > [!IMPORTANT]
85
+ > **Important:** Engage SDK has superseded Media Home, which is now deprecated. If you have an existing Media Home integration, follow the instructions in [Step
86
+ > 0](https://developer.android.com/guide/playcore/engage/watch#migration) to migrate your content to Engage SDK, which allows your content to be published to more devices and form factors. Contact [`engage-developers@google.com`](mailto:engage-developers@google.com). If you don't have an existing Media Home integration, skip to [Step
87
+ > 1](https://developer.android.com/guide/playcore/engage/watch#provide-entity-data).
88
+
89
+ ### Step 0: Migration from existing Media Home SDK integration
90
+
91
+ #### Map data models from existing integration
92
+
93
+ If you are migrating from an existing Media Home integration, the following
94
+ table outlines how to map data models in existing SDKs to the new Engage SDK:
95
+
96
+ | MediaHomeVideoContract integration equivalent | Engage SDK integration equivalent |
97
+ |---|---|
98
+ | `com.google.android.mediahome.video.PreviewChannel` | ` com.google.android.engage.common.datamodel.RecommendationCluster ` |
99
+ | `com.google.android.mediahome.video.PreviewChannel.Builder` | ` com.google.android.engage.common.datamodel.RecommendationCluster.Builder ` |
100
+ | `com.google.android.mediahome.video.PreviewChannelHelper` | `com.google.android.engage.video.service.AppEngageVideoClient` |
101
+ | `com.google.android.mediahome.video.PreviewProgram` | Divided into separate classes: `EventVideo`, `LiveStreamingVideo`, `Movie`, `TvEpisode`, `TvSeason`, `TvShow`, `VideoClipEntity` |
102
+ | `com.google.android.mediahome.video.PreviewProgram.Builder` | Divided into builders in separate classes: `EventVideo`, `LiveStreamingVideo`, `Movie`, `TvEpisode`, `TvSeason`, `TvShow`, `VideoClipEntity` |
103
+ | `com.google.android.mediahome.video.VideoContract` | No longer needed. |
104
+ | `com.google.android.mediahome.video.WatchNextProgram` | Divided into attributes in separate classes: `EventVideoEntity`, `LiveStreamingVideoEntity`, `MovieEntity`, `TvEpisodeEntity`, `TvSeasonEntity`, `TvShowEntity`, `VideoClipEntity` |
105
+ | `com.google.android.mediahome.video.WatchNextProgram.Builder` | Divided into attributes in separate classes: `EventVideoEntity`, `LiveStreamingVideoEntity`, `MovieEntity`, `TvEpisodeEntity`, `TvSeasonEntity`, `TvShowEntity`, `VideoClipEntity` |
106
+
107
+ #### Publishing clusters in Media Home SDK vs Engage SDK
108
+
109
+ With Media Home SDK, clusters and entities were published through separate APIs:
110
+
111
+ // 1. Fetch existing channels
112
+ List<PreviewChannel> channels = PreviewChannelHelper.getAllChannels();
113
+
114
+ // 2. If there are no channels, publish new channels
115
+ long channelId = PreviewChannelHelper.publishChannel(builder.build());
116
+
117
+ // 3. If there are existing channels, decide whether to update channel contents
118
+ PreviewChannelHelper.updatePreviewChannel(channelId, builder.build());
119
+
120
+ // 4. Delete all programs in the channel
121
+ PreviewChannelHelper.deleteAllPreviewProgramsByChannelId(channelId);
122
+
123
+ // 5. publish new programs in the channel
124
+ PreviewChannelHelper.publishPreviewProgram(builder.build());
125
+
126
+ With Engage SDK, cluster and entity publishing are combined into a single API
127
+ call. All entities that belong to a cluster are published together with that
128
+ cluster:
129
+
130
+ ### Kotlin
131
+
132
+ RecommendationCluster.Builder()
133
+ .addEntity(MOVIE_ENTITY)
134
+ .addEntity(MOVIE_ENTITY)
135
+ .addEntity(MOVIE_ENTITY)
136
+ .setTitle("Top Picks For You")
137
+ .build()
138
+
139
+ ### Java
140
+
141
+ new RecommendationCluster.Builder()
142
+ .addEntity(MOVIE_ENTITY)
143
+ .addEntity(MOVIE_ENTITY)
144
+ .addEntity(MOVIE_ENTITY)
145
+ .setTitle("Top Picks For You")
146
+ .build();
147
+
148
+ ### Step 1: Provide entity data
149
+
150
+ The SDK has defined different entities to represent each item type. We support
151
+ the following entities for the Watch category:
152
+
153
+ 1. [`MovieEntity`](https://developer.android.com/guide/playcore/engage/watch#movieentity)
154
+ 2. [`TvShowEntity`](https://developer.android.com/guide/playcore/engage/watch#tvshowentity)
155
+ 3. [`TvSeasonEntity`](https://developer.android.com/guide/playcore/engage/watch#tvseasonentity)
156
+ 4. [`TvEpisodeEntity`](https://developer.android.com/guide/playcore/engage/watch#tvepisodeentity)
157
+ 5. [`LiveStreamingVideoEntity`](https://developer.android.com/guide/playcore/engage/watch#livestreamingvideoentity)
158
+ 6. [`VideoClipEntity`](https://developer.android.com/guide/playcore/engage/watch#videoclipentity)
159
+
160
+ The following chart outlines attributes and requirements for each type.
161
+
162
+ #### `MovieEntity`
163
+
164
+ | Attribute | Requirement | Notes |
165
+ |---|---|---|
166
+ | Name | **Required** | |
167
+ | Poster images | **Required** | At least one image is required, and must be provided with an aspect ratio. (Landscape is preferred but passing both portrait and landscape images for different scenarios is recommended.) See [Image Specifications](https://developer.android.com/guide/playcore/engage/watch#image-specs) for guidance. |
168
+ | Playback uri | **Required** | The deep link to the provider app to start playing the movie. Note: You can use deep links for attribution. [Refer to this FAQ](https://developer.android.com/guide/playcore/engage/faq#deeplinks-attribution) |
169
+ | Info page uri | Optional | The deep link to the provider app to show details about the movie. Note: You can use deep links for attribution. [Refer to this FAQ](https://developer.android.com/guide/playcore/engage/faq#deeplinks-attribution) |
170
+ | Release date | Optional | In epoch milliseconds. |
171
+ | Availability | **Required** | AVAILABLE: The content is available to the user without any further action. FREE_WITH_SUBSCRIPTION: The content is available after the user purchases a subscription. PAID_CONTENT: The content requires user purchase or rental. PURCHASED: The content has been purchased or rented by the user. |
172
+ | Offer price | Optional | Free text |
173
+ | Duration | **Required** | In milliseconds. |
174
+ | Genre | **Required** | Free text |
175
+ | Content ratings | Optional | Free text, follow the industry standard. ([Example](https://www.spectrum.net/support/tv/tv-and-movie-ratings-descriptions)) |
176
+ | Call to action text | Optional | Free text to be displayed as a call to action. |
177
+ | Tags | Optional | List of tags associated with the entity. |
178
+ | Watch next type | Conditionally required | Must be provided when the item is in the Continuation cluster and must be one of the following four types: CONTINUE: The user has already watched more than 1 minute of this content. NEW: The user has watched all available episodes from some episodic content, but a new episode has become available and there is exactly one unwatched episode. This works for TV shows, recorded soccer matches in a series, and so on. NEXT: The user has watched one or more complete episodes from some episodic content, but there remains either more than one episode remaining or exactly one episode remaining where the last episode is not "NEW" and was released before the user started watching the episodic content. WATCHLIST: The user has explicitly elected to add a movie, event, or series to a watchlist to manually curate what they want to watch next. |
179
+ | Last engagement time | Conditionally required | Must be provided when the item is in the Continuation cluster. In epoch milliseconds. |
180
+ | Last playback position time | Conditionally required | Must be provided when the item is in the Continuation cluster and WatchNextType is CONTINUE. In epoch milliseconds. |
181
+
182
+ #### `TvShowEntity`
183
+
184
+ | Attribute | Requirement | Notes |
185
+ |---|---|---|
186
+ | Name | **Required** | |
187
+ | Poster images | **Required** | At least one image is required, and must be provided with an aspect ratio. (Landscape is preferred but passing both portrait and landscape images for different scenarios is recommended.) See [Image Specifications](https://developer.android.com/guide/playcore/engage/watch#image-specs) for guidance. |
188
+ | Info page uri | **Required** | The deep link to the provider app to show the details of the TV show. Note: You can use deep links for attribution. [Refer to this FAQ](https://developer.android.com/guide/playcore/engage/faq#deeplinks-attribution) |
189
+ | Playback uri | Optional | The deep link to the provider app to start playing the TV show. Note: You can use deep links for attribution. [Refer to this FAQ](https://developer.android.com/guide/playcore/engage/faq#deeplinks-attribution) |
190
+ | First episode air date | Optional | In epoch milliseconds. |
191
+ | Latest episode air date | Optional | In epoch milliseconds. |
192
+ | Availability | **Required** | AVAILABLE: The content is available to the user without any further action. FREE_WITH_SUBSCRIPTION: The content is available after the user purchases a subscription. PAID_CONTENT: The content requires user purchase or rental. PURCHASED: The content has been purchased or rented by the user. |
193
+ | Offer price | Optional | Free text |
194
+ | Season count | **Required** | Positive integer |
195
+ | Genre | **Required** | Free text |
196
+ | Content ratings | Optional | Free text, follow the industry standard. ([Example](https://www.spectrum.net/support/tv/tv-and-movie-ratings-descriptions)) |
197
+ | Call to action text | Optional | Free text to be displayed as a call to action. |
198
+ | Tags | Optional | List of tags associated with the entity. |
199
+ | Watch next type | Conditionally required | Must be provided when the item is in the Continuation cluster and must be one of the following four types: CONTINUE: The user has already watched more than 1 minute of this content. NEW: The user has watched all available episodes from some episodic content, but a new episode has become available and there is exactly one unwatched episode. This works for TV shows, recorded soccer matches in a series, and so on. NEXT: The user has watched one or more complete episodes from some episodic content, but there remains either more than one episode remaining or exactly one episode remaining where the last episode is not "NEW" and was released before the user started watching the episodic content. WATCHLIST: The user has explicitly elected to add a movie, event, or series to a watchlist to manually curate what they want to watch next. |
200
+ | Last engagement time | Conditionally required | Must be provided when the item is in the Continuation cluster. In epoch milliseconds. |
201
+ | Last playback position time | Conditionally required | Must be provided when the item is in the Continuation cluster and WatchNextType is CONTINUE. In epoch milliseconds. |
202
+
203
+ #### `TvSeasonEntity`
204
+
205
+ | Attribute | Requirement | Notes |
206
+ |---|---|---|
207
+ | Name | **Required** | |
208
+ | Poster images | **Required** | At least one image is required, and must be provided with an aspect ratio. (Landscape is preferred but passing both portrait and landscape images for different scenarios is recommended.) See [Image Specifications](https://developer.android.com/guide/playcore/engage/watch#image-specs) for guidance. |
209
+ | Info page uri | **Required** | The deep link to the provider app to show the details of the TV show season. Note: You can use deep links for attribution. [Refer to this FAQ](https://developer.android.com/guide/playcore/engage/faq#deeplinks-attribution) |
210
+ | Playback uri | Optional | The deep link to the provider app to start playing the TV show season. Note: You can use deep links for attribution. [Refer to this FAQ](https://developer.android.com/guide/playcore/engage/faq#deeplinks-attribution) |
211
+ | Display Season number | **Optional** **Available in v1.3.1** | String |
212
+ | First episode air date | Optional | In epoch milliseconds. |
213
+ | Latest episode air date | Optional | In epoch milliseconds. |
214
+ | Availability | **Required** | AVAILABLE: The content is available to the user without any further action. FREE_WITH_SUBSCRIPTION: The content is available after the user purchases a subscription. PAID_CONTENT: The content requires user purchase or rental. PURCHASED: The content has been purchased or rented by the user. |
215
+ | Offer price | Optional | Free text |
216
+ | Episode count | **Required** | Positive integer |
217
+ | Genre | **Required** | Free text |
218
+ | Content ratings | Optional | Free text, follow the industry standard. ([Example](https://www.spectrum.net/support/tv/tv-and-movie-ratings-descriptions)) |
219
+ | Call to action text | Optional | Free text to be displayed as a call to action. |
220
+ | Tags | Optional | List of tags associated with the entity. |
221
+ | Watch next type | Conditionally required | Must be provided when the item is in the Continuation cluster and must be one of the following four types: CONTINUE: The user has already watched more than 1 minute of this content. NEW: The user has watched all available episodes from some episodic content, but a new episode has become available and there is exactly one unwatched episode. This works for TV shows, recorded soccer matches in a series, and so on. NEXT: The user has watched one or more complete episodes from some episodic content, but there remains either more than one episode remaining or exactly one episode remaining where the last episode is not "NEW" and was released before the user started watching the episodic content. WATCHLIST: The user has explicitly elected to add a movie, event, or series to a watchlist to manually curate what they want to watch next. |
222
+ | Last engagement time | Conditionally required | Must be provided when the item is in the Continuation cluster. In epoch milliseconds. |
223
+ | Last playback position time | Conditionally required | Must be provided when the item is in the Continuation cluster and WatchNextType is CONTINUE. In epoch milliseconds. |
224
+
225
+ #### `TvEpisodeEntity`
226
+
227
+ | Attribute | Requirement | Notes |
228
+ |---|---|---|
229
+ | Name | **Required** | |
230
+ | Poster images | **Required** | At least one image is required, and must be provided with an aspect ratio. (Landscape is preferred but passing both portrait and landscape images for different scenarios is recommended.) See [Image Specifications](https://developer.android.com/guide/playcore/engage/watch#image-specs) for guidance. |
231
+ | Playback uri | **Required** | The deep link to the provider app to start playing the episode. Note: You can use deep links for attribution. [Refer to this FAQ](https://developer.android.com/guide/playcore/engage/faq#deeplinks-attribution) |
232
+ | Info page uri | Optional | The deep link to the provider app to show details about the TV show episode. Note: You can use deep links for attribution. [Refer to this FAQ](https://developer.android.com/guide/playcore/engage/faq#deeplinks-attribution) |
233
+ | Display Episode number | **Optional** **Available in v1.3.1** | String |
234
+ | Air date | **Required** | In epoch milliseconds. |
235
+ | Availability | **Required** | AVAILABLE: The content is available to the user without any further action. FREE_WITH_SUBSCRIPTION: The content is available after the user purchases a subscription. PAID_CONTENT: The content requires user purchase or rental. PURCHASED: The content has been purchased or rented by the user. |
236
+ | Offer price | Optional | Free text |
237
+ | Duration | **Required** | Must be a positive value in milliseconds. |
238
+ | Genre | **Required** | Free text |
239
+ | Content ratings | Optional | Free text, follow the industry standard. ([Example](https://www.spectrum.net/support/tv/tv-and-movie-ratings-descriptions)) |
240
+ | Call to action text | Optional | Free text to be displayed as a call to action. |
241
+ | Tags | Optional | List of tags associated with the entity. |
242
+ | Watch next type | Conditionally required | Must be provided when the item is in the Continuation cluster and must be one of the following four types: CONTINUE: The user has already watched more than 1 minute of this content. NEW: The user has watched all available episodes from some episodic content, but a new episode has become available and there is exactly one unwatched episode. This works for TV shows, recorded soccer matches in a series, and so on. NEXT: The user has watched one or more complete episodes from some episodic content, but there remains either more than one episode remaining or exactly one episode remaining where the last episode is not "NEW" and was released before the user started watching the episodic content. WATCHLIST: The user has explicitly elected to add a movie, event, or series to a watchlist to manually curate what they want to watch next. |
243
+ | Last engagement time | Conditionally required | Must be provided when the item is in the Continuation cluster. In epoch milliseconds. |
244
+ | Last playback position time | Conditionally required | Must be provided when the item is in the Continuation cluster and WatchNextType is CONTINUE. In epoch milliseconds. |
245
+
246
+ #### `LiveStreamingVideoEntity`
247
+
248
+ | Attribute | Requirement | Notes |
249
+ |---|---|---|
250
+ | Name | **Required** | |
251
+ | Poster images | **Required** | At least one image is required, and must be provided with an aspect ratio. (Landscape is preferred but passing both portrait and landscape images for different scenarios is recommended.) See [Image Specifications](https://developer.android.com/guide/playcore/engage/watch#image-specs) for guidance. |
252
+ | Playback uri | **Required** | The deep link to the provider app to start playing the video. Note: You can use deep links for attribution. [Refer to this FAQ](https://developer.android.com/guide/playcore/engage/faq#deeplinks-attribution) |
253
+ | Broadcaster | **Required** | Free text |
254
+ | Start time | Optional | In epoch milliseconds. |
255
+ | End time | Optional | In epoch milliseconds. |
256
+ | View count | Optional | Free text, must be localized. |
257
+ | Call to action text | Optional | Free text to be displayed as a call to action. |
258
+ | Tags | Optional | List of tags associated with the entity. |
259
+ | Watch next type | Conditionally required | Must be provided when the item is in the Continuation cluster and must be one of the following four types: CONTINUE: The user has already watched more than 1 minute of this content. NEW: The user has watched all available episodes from some episodic content, but a new episode has become available and there is exactly one unwatched episode. This works for TV shows, recorded soccer matches in a series, and so on. NEXT: The user has watched one or more complete episodes from some episodic content, but there remains either more than one episode remaining or exactly one episode remaining where the last episode is not "NEW" and was released before the user started watching the episodic content. WATCHLIST: The user has explicitly elected to add a movie, event, or series to a watchlist to manually curate what they want to watch next. |
260
+ | Last engagement time | Conditionally required | Must be provided when the item is in the Continuation cluster. In epoch milliseconds. |
261
+ | Last playback position time | Conditionally required | Must be provided when the item is in the Continuation cluster and WatchNextType is CONTINUE. In epoch milliseconds. |
262
+
263
+ #### `VideoClipEntity`
264
+
265
+ The `VideoClipEntity` object represents a video entity coming from social media,
266
+ such as TikTok or YouTube.
267
+
268
+ | Attribute | Requirement | Notes |
269
+ |---|---|---|
270
+ | Name | **Required** | |
271
+ | Poster images | **Required** | At least one image is required, and must be provided with an aspect ratio. (Landscape is preferred but passing both portrait and landscape images for different scenarios is recommended.) See [Image Specifications](https://developer.android.com/guide/playcore/engage/watch#image-specs) for guidance. |
272
+ | Playback uri | **Required** | The deep link to the provider app to start playing the video. Note: You can use deep links for attribution. [Refer to this FAQ](https://developer.android.com/guide/playcore/engage/faq#deeplinks-attribution) |
273
+ | Created time | **Required** | In epoch milliseconds. |
274
+ | Duration | **Required** | Must be a positive value in milliseconds. |
275
+ | Creator | **Required** | Free text |
276
+ | Creator image | Optional | Image of the Creator avatar |
277
+ | View count | Optional | Free text, must be localized. |
278
+ | Call to action text | Optional | Free text to be displayed as a call to action. |
279
+ | Tags | Optional | List of tags associated with the entity. |
280
+ | Watch next type | Conditionally required | Must be provided when the item is in the Continuation cluster and must be one of the following four types: CONTINUE: The user has already watched more than 1 minute of this content. NEW: The user has watched all available episodes from some episodic content, but a new episode has become available and there is exactly one unwatched episode. This works for TV shows, recorded soccer matches in a series, and so on. NEXT: The user has watched one or more complete episodes from some episodic content, but there remains either more than one episode remaining or exactly one episode remaining where the last episode is not "NEW" and was released before the user started watching the episodic content. WATCHLIST: The user has explicitly elected to add a movie, event, or series to a watchlist to manually curate what they want to watch next. |
281
+ | Last engagement time | Conditionally required | Must be provided when the item is in the Continuation cluster. In epoch milliseconds. |
282
+ | Last playback position time | Conditionally required | Must be provided when the item is in the Continuation cluster and WatchNextType is CONTINUE. In epoch milliseconds. |
283
+
284
+ #### Image specifications
285
+
286
+ The following section lists the required specifications for image assets:
287
+
288
+ *File formats*
289
+
290
+ PNG, JPG, static GIF, WebP
291
+
292
+ *Maximum file size*
293
+
294
+ 5120 KB
295
+
296
+ *Additional recommendations*
297
+
298
+ - **Image safe area:** Put your important content in the center 80% of the image.
299
+
300
+ #### Example
301
+
302
+ ### Kotlin
303
+
304
+ var movie = MovieEntity.Builder()
305
+ .setName("Avengers")
306
+ .addPosterImage(Image.Builder()
307
+ .setImageUri(Uri.parse("http://www.x.com/image.png"))
308
+ .setImageHeightInPixel(960)
309
+ .setImageWidthInPixel(408)
310
+ .build())
311
+ .setPlayBackUri(Uri.parse("http://tv.com/playback/1"))
312
+ .setReleaseDateEpochMillis(1633032895L)
313
+ .setAvailability(ContentAvailability.AVAILABILITY_AVAILABLE)
314
+ .setDurationMillis(12345678L)
315
+ .addGenre("action")
316
+ .addContentRating("R")
317
+ .setWatchNextType(WatchNextType.TYPE_NEW)
318
+ .setLastEngagementTimeMillis(1664568895L)
319
+ .setCallToActionText("Watch Now")
320
+ .addTag("Action")
321
+ .build()
322
+
323
+ ### Java
324
+
325
+ MovieEntity movie = new MovieEntity.Builder()
326
+ .setName("Avengers")
327
+ .addPosterImage(
328
+ new Image.Builder()
329
+ .setImageUri(Uri.parse("http://www.x.com/image.png"))
330
+ .setImageHeightInPixel(960)
331
+ .setImageWidthInPixel(408)
332
+ .build())
333
+ .setPlayBackUri(Uri.parse("http://tv.com/playback/1"))
334
+ .setReleaseDateEpochMillis(1633032895L)
335
+ .setAvailability(ContentAvailability.AVAILABILITY_AVAILABLE)
336
+ .setDurationMillis(12345678L)
337
+ .addGenre("action")
338
+ .addContentRating("R")
339
+ .setWatchNextType(WatchNextType.TYPE_NEW)
340
+ .setLastEngagementTimeMillis(1664568895L)
341
+ .setCallToActionText("Watch Now")
342
+ .addTag("Action")
343
+ .build();
344
+
345
+ ### Step 2: Provide Cluster data
346
+
347
+ It's recommended to have the content publish job executed in the background
348
+ (for example, using [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager))
349
+ and scheduled on a regular basis or on an event basis (for example, every time
350
+ the user opens the app or when the user just added something to their cart).
351
+
352
+ `AppEngagePublishClient` is responsible for publishing clusters. Following
353
+ APIs are available in the client:
354
+
355
+ - `isServiceAvailable`
356
+ - `publishRecommendationClusters`
357
+ - `publishFeaturedCluster`
358
+ - `publishContinuationCluster`
359
+ - `publishUserAccountManagementRequest`
360
+ - `updatePublishStatus`
361
+ - `deleteRecommendationsClusters`
362
+ - `deleteFeaturedCluster`
363
+ - `deleteContinuationCluster`
364
+ - `deleteUserManagementCluster`
365
+ - `deleteClusters`
366
+
367
+ #### `isServiceAvailable`
368
+
369
+ This API is used to check if the service is available for integration and
370
+ whether the content can be presented on the device.
371
+
372
+ ##### For Engage SDK v1.6.0 and higher (Recommended)
373
+
374
+
375
+ ## Android skills
376
+
377
+ [View on GitHub](https://github.com/android/skills/tree/main/play/engage-sdk-integration)
378
+
379
+ ### Engage SDK integration
380
+
381
+ To install the skill from the [Android CLI](https://developer.android.com/tools/agents/android-cli), run:
382
+
383
+ android skills add engage-sdk-integration
384
+
385
+ If your team uses AI coding tools (such as Gemini in Android Studio), you can automate this migration by prompting your AI assistant:
386
+
387
+ Use the engage-sdk-integration skill to use Engage SDK 1.6.0 and refactor isServiceAvailable to pass ServiceAvailabilityRequest for publishing all cluster types.
388
+
389
+ <br />
390
+
391
+ You can check the service availability for every cluster type that you intend to
392
+ publish. The `isServiceAvailable` API accepts a request object,
393
+ `ServiceAvailabilityRequest`, which contains the cluster types for which service
394
+ availability needs to be checked. You can find the `ClusterType` enum values
395
+ required for `ServiceAvailabilityRequest` from the following table.
396
+
397
+ | Cluster Type | Cluster Type Constant | Integer Value |
398
+ |---|---|---|
399
+ | Unknown | `TYPE_UNKNOWN` | 0 |
400
+ | Recommendation Cluster | `TYPE_RECOMMENDATION` | 1 |
401
+ | Featured Cluster | `TYPE_FEATURED` | 2 |
402
+ | Continuation Cluster | `TYPE_CONTINUATION` | 3 |
403
+ | User Management Cluster | `TYPE_ENGAGEMENT` | 8 |
404
+ | Subscription Cluster | `TYPE_SUBSCRIPTION` | 12 |
405
+
406
+ ### Kotlin
407
+
408
+ val request = ServiceAvailabilityRequest.Builder()
409
+ .addIntendedClusterType(ClusterType.TYPE_CONTINUATION)
410
+ .addIntendedClusterType(ClusterType.TYPE_RECOMMENDATION)
411
+ .build()
412
+
413
+ client.isServiceAvailable(request).addOnCompleteListener { task ->
414
+ if (task.isSuccessful) {
415
+ val availabilityMap = task.result
416
+ if (availabilityMap[ClusterType.TYPE_CONTINUATION] == true) {
417
+ // Proceed with publishing continuation content
418
+ }
419
+ if (availabilityMap[ClusterType.TYPE_RECOMMENDATION] == true) {
420
+ // Proceed with publishing recommendation content
421
+ }
422
+ } else {
423
+ // The IPC call itself fails, proceed with error handling logic here,
424
+ // such as retry.
425
+ }
426
+ }
427
+
428
+ ### Java
429
+
430
+ ServiceAvailabilityRequest request =
431
+ new ServiceAvailabilityRequest.Builder()
432
+ .addIntendedClusterType(ClusterType.TYPE_CONTINUATION)
433
+ .addIntendedClusterType(ClusterType.TYPE_RECOMMENDATION)
434
+ .build();
435
+
436
+ client.isServiceAvailable(request).addOnCompleteListener(task -> {
437
+ if (task.isSuccessful()) {
438
+ Map<Integer, Boolean> availabilityMap = task.getResult();
439
+ if (Boolean.TRUE.equals(availabilityMap.get(ClusterType.TYPE_CONTINUATION))) {
440
+ // Proceed with publishing continuation content
441
+ }
442
+ if (Boolean.TRUE.equals(availabilityMap.get(ClusterType.TYPE_RECOMMENDATION))) {
443
+ // Proceed with publishing recommendation content
444
+ }
445
+ } else {
446
+ // The IPC call itself fails, proceed with error handling logic here,
447
+ // such as retry.
448
+ }
449
+ });
450
+
451
+ ###### Conditional Service Availability Feature
452
+
453
+ Some integrated apps request a special configuration that enables and disables
454
+ the Engage service intermittently in order to reduce their serving cost. This
455
+ intermittent content ingestion strategy, although possible, negatively affects
456
+ the user and the product -- stale content will not be presented and some surfaces
457
+ will not be served at all.
458
+
459
+ Starting with v1.6.0, the Engage SDK allows checking availability for specific
460
+ cluster types. This provides more flexibility so that if the intermittent
461
+ content strategy was adopted by a given application, some cluster types can
462
+ follow that intermittent strategy while other cluster types are always enabled
463
+ (i.e. continuation clusters).
464
+
465
+ If the Engage service should not be 'continuously' enabled on all supported
466
+ devices for whatever reason, and is configured for intermittent ingestion for
467
+ any set of devices, all continuation cluster publications (e.g. Continue
468
+ Watching) will be still enabled by default configuration, and the rest of the
469
+ cluster types will be enabled and disabled intermittently. If intermittent
470
+ ingestion applies to you but this default configuration is not suitable for
471
+ your needs, please contact engage-developers@google.com.
472
+
473
+ ##### For SDK versions prior to v1.6.0 (Deprecated)
474
+
475
+ ### Kotlin
476
+
477
+ client.isServiceAvailable.addOnCompleteListener { task ->
478
+ if (task.isSuccessful) {
479
+ // Handle IPC call success
480
+ if(task.result) {
481
+ // Service is available on the device, proceed with content publish
482
+ // calls.
483
+ } else {
484
+ // Service is not available, no further action is needed.
485
+ }
486
+ } else {
487
+ // The IPC call itself fails, proceed with error handling logic here,
488
+ // such as retry.
489
+ }
490
+ }
491
+
492
+ ### Java
493
+
494
+ client.isServiceAvailable().addOnCompleteListener(task - > {
495
+ if (task.isSuccessful()) {
496
+ // Handle success
497
+ if(task.getResult()) {
498
+ // Service is available on the device, proceed with content publish
499
+ // calls.
500
+ } else {
501
+ // Service is not available, no further action is needed.
502
+ }
503
+ } else {
504
+ // The IPC call itself fails, proceed with error handling logic here,
505
+ // such as retry.
506
+ }
507
+ });
508
+
509
+ > [!NOTE]
510
+ > **Note:** We highly recommend keeping a periodic job running to check if the service becomes available at a later point in time. The availability of the service may change with Android version upgrades, app upgrades, installs, and uninstalls. By ensuring periodic job checks at a certain time interval, data can be published once the service becomes available.
511
+
512
+ #### `publishRecommendationClusters`
513
+
514
+ This API is used to publish a list of `RecommendationCluster` objects.
515
+
516
+ > [!IMPORTANT]
517
+ > **Important:** The publish APIs are upsert APIs; it replaces the existing content. **Don't** call delete and publish APIs subsequently to replace the content as the publish APIs do that inherently.
518
+
519
+ ### Kotlin
520
+
521
+ client.publishRecommendationClusters(
522
+ PublishRecommendationClustersRequest.Builder()
523
+ .addRecommendationCluster(
524
+ RecommendationCluster.Builder()
525
+ .addEntity(entity1)
526
+ .addEntity(entity2)
527
+ .setTitle("Top Picks For You")
528
+ .build()
529
+ )
530
+ .build()
531
+ )
532
+
533
+ ### Java
534
+
535
+ client.publishRecommendationClusters(
536
+ new PublishRecommendationClustersRequest.Builder()
537
+ .addRecommendationCluster(
538
+ new RecommendationCluster.Builder()
539
+ .addEntity(entity1)
540
+ .addEntity(entity2)
541
+ .setTitle("Top Picks For You")
542
+ .build())
543
+ .build());
544
+
545
+ When the service receives the request, the following actions take place within
546
+ one transaction:
547
+
548
+ - Existing `RecommendationCluster` data from the developer partner is removed.
549
+ - Data from the request is parsed and stored in the updated Recommendation Cluster.
550
+
551
+ In case of an error, the entire request is rejected and the existing state is
552
+ maintained.
553
+
554
+ #### `publishFeaturedCluster`
555
+
556
+ This API is used to publish a list of `FeaturedCluster` objects.
557
+
558
+ > [!IMPORTANT]
559
+ > **Important:** The publish APIs are upsert APIs; it replaces the existing content. **Don't** call delete and publish APIs subsequently to replace the content as the publish APIs do that inherently.
560
+
561
+ ### Kotlin
562
+
563
+ client.publishFeaturedCluster(
564
+ PublishFeaturedClusterRequest.Builder()
565
+ .setFeaturedCluster(
566
+ FeaturedCluster.Builder()
567
+ .addEntity(entity1)
568
+ .addEntity(entity2)
569
+ .build())
570
+ .build())
571
+
572
+ ### Java
573
+
574
+ client.publishFeaturedCluster(
575
+ new PublishFeaturedClustersRequest.Builder()
576
+ .addFeaturedCluster(
577
+ new FeaturedCluster.Builder()
578
+ .addEntity(entity1)
579
+ .addEntity(entity2)
580
+ .build())
581
+ .build());
582
+
583
+ When the service receives the request, the following actions take place within
584
+ one transaction:
585
+
586
+ - Existing `FeaturedCluster` data from the developer partner is removed.
587
+ - Data from the request is parsed and stored in the updated Featured Cluster.
588
+
589
+ In case of an error, the entire request is rejected and the existing state is
590
+ maintained.
591
+
592
+ #### `publishContinuationCluster`
593
+
594
+ This API is used to publish a `ContinuationCluster` object.
595
+
596
+ > [!IMPORTANT]
597
+ > **Important:** The publish APIs are upsert APIs; it replaces the existing content. **Don't** call delete and publish APIs subsequently to replace the content as the publish APIs do that inherently.
598
+
599
+ ### Kotlin
600
+
601
+ client.publishContinuationCluster(
602
+ PublishContinuationClusterRequest.Builder()
603
+ .setContinuationCluster(
604
+ ContinuationCluster.Builder()
605
+ .addEntity(entity1)
606
+ .addEntity(entity2)
607
+ .build())
608
+ .build())
609
+
610
+ ### Java
611
+
612
+ client.publishContinuationCluster(
613
+ new PublishContinuationClusterRequest.Builder()
614
+ .setContinuationCluster(
615
+ new ContinuationCluster.Builder()
616
+ .addEntity(entity1)
617
+ .addEntity(entity2)
618
+ .build())
619
+ .build());
620
+
621
+ When the service receives the request, the following actions take place within
622
+ one transaction:
623
+
624
+ - Existing `ContinuationCluster` data from the developer partner is removed.
625
+ - Data from the request is parsed and stored in the updated Continuation Cluster.
626
+
627
+ In case of an error, the entire request is rejected and the existing state is
628
+ maintained.
629
+
630
+ #### `publishUserAccountManagementRequest`
631
+
632
+ This API is used to publish a Sign In card . The signin action directs users to
633
+ the app's sign in page so that the app can publish content (or provide more
634
+ personalized content)
635
+
636
+ The following metadata is part of the Sign In Card -
637
+
638
+ | Attribute | Requirement | Description |
639
+ |---|---|---|
640
+ | Action Uri | Required | Deeplink to Action (i.e. navigates to app sign in page) |
641
+ | Image | Optional - If not provided, Title must be provided | Image Shown on the Card 16x9 aspect ratio images with a resolution of 1264x712 |
642
+ | Title | Optional - If not provided, Image must be provided | Title on the Card |
643
+ | Action Text | Optional | Text Shown on the CTA (i.e. Sign in) |
644
+ | Subtitle | Optional | Optional Subtitle on the Card |
645
+
646
+ > [!IMPORTANT]
647
+ > **Important:** The publish APIs are upsert APIs; it replaces the existing content. **Don't** call delete and publish APIs subsequently to replace the content as the publish APIs do that inherently.
648
+
649
+ ### Kotlin
650
+
651
+ var SIGN_IN_CARD_ENTITY =
652
+ SignInCardEntity.Builder()
653
+ .addPosterImage(
654
+ Image.Builder()
655
+ .setImageUri(Uri.parse("http://www.x.com/image.png"))
656
+ .setImageHeightInPixel(500)
657
+ .setImageWidthInPixel(500)
658
+ .build())
659
+ .setActionText("Sign In")
660
+ .setActionUri(Uri.parse("http://xx.com/signin"))
661
+ .build()
662
+
663
+ client.publishUserAccountManagementRequest(
664
+ PublishUserAccountManagementRequest.Builder()
665
+ .setSignInCardEntity(SIGN_IN_CARD_ENTITY)
666
+ .build());
667
+
668
+ ### Java
669
+
670
+ SignInCardEntity SIGN_IN_CARD_ENTITY =
671
+ new SignInCardEntity.Builder()
672
+ .addPosterImage(
673
+ new Image.Builder()
674
+ .setImageUri(Uri.parse("http://www.x.com/image.png"))
675
+ .setImageHeightInPixel(500)
676
+ .setImageWidthInPixel(500)
677
+ .build())
678
+ .setActionText("Sign In")
679
+ .setActionUri(Uri.parse("http://xx.com/signin"))
680
+ .build();
681
+
682
+ client.publishUserAccountManagementRequest(
683
+ new PublishUserAccountManagementRequest.Builder()
684
+ .setSignInCardEntity(SIGN_IN_CARD_ENTITY)
685
+ .build());
686
+
687
+ When the service receives the request, the following actions take place within
688
+ one transaction:
689
+
690
+ - Existing `UserAccountManagementCluster` data from the developer partner is removed.
691
+ - Data from the request is parsed and stored in the updated UserAccountManagementCluster Cluster.
692
+
693
+ In case of an error, the entire request is rejected and the existing state is
694
+ maintained.
695
+
696
+ #### `updatePublishStatus`
697
+
698
+ If for any internal business reason, none of the clusters is published,
699
+ we **strongly recommend** updating the publish status using the
700
+ **updatePublishStatus** API.
701
+ This is important because :
702
+
703
+ - Providing the status in all scenarios, even when the content is published (STATUS == PUBLISHED), is critical to populate dashboards that use this explicit status to convey the health and other metrics of your integration.
704
+ - If no content is published but the integration status isn't broken (STATUS == NOT_PUBLISHED), Google can avoid triggering alerts in the app health dashboards. It confirms that content is not published due to an **expected** situation from the provider's standpoint.
705
+ - It helps developers provide insights into when the data is published versus not.
706
+ - Google may use the status codes to nudge the user to do certain actions in the app so they can see the app content or overcome it.
707
+
708
+ The list of eligible publish status codes are :
709
+
710
+ // Content is published
711
+ AppEngagePublishStatusCode.PUBLISHED,
712
+
713
+ // Content is not published as user is not signed in
714
+ AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN,
715
+
716
+ // Content is not published as user is not subscribed
717
+ AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SUBSCRIPTION,
718
+
719
+ // Content is not published as user location is ineligible
720
+ AppEngagePublishStatusCode.NOT_PUBLISHED_INELIGIBLE_LOCATION,
721
+
722
+ // Content is not published as there is no eligible content
723
+ AppEngagePublishStatusCode.NOT_PUBLISHED_NO_ELIGIBLE_CONTENT,
724
+
725
+ // Content is not published as the feature is disabled by the client
726
+ // Available in v1.3.1
727
+ AppEngagePublishStatusCode.NOT_PUBLISHED_FEATURE_DISABLED_BY_CLIENT,
728
+
729
+ // Content is not published as the feature due to a client error
730
+ // Available in v1.3.1
731
+ AppEngagePublishStatusCode.NOT_PUBLISHED_CLIENT_ERROR,
732
+
733
+ // Content is not published as the feature due to a service error
734
+ // Available in v1.3.1
735
+ AppEngagePublishStatusCode.NOT_PUBLISHED_SERVICE_ERROR,
736
+
737
+ // Content is not published due to some other reason
738
+ // Reach out to engage-developers@ before using this enum.
739
+ AppEngagePublishStatusCode.NOT_PUBLISHED_OTHER
740
+
741
+ If the content is not published due to a user not logged in,
742
+ Google would recommend publishing the Sign In Card.
743
+ If for any reason providers are not able to publish the Sign In Card
744
+ then we recommend calling the **updatePublishStatus** API
745
+ with the status code **NOT_PUBLISHED_REQUIRES_SIGN_IN**
746
+
747
+ ### Kotlin
748
+
749
+ client.updatePublishStatus(
750
+ PublishStatusRequest.Builder()
751
+ .setStatusCode(AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN)
752
+ .build())
753
+
754
+ ### Java
755
+
756
+ client.updatePublishStatus(
757
+ new PublishStatusRequest.Builder()
758
+ .setStatusCode(AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN)
759
+ .build());
760
+
761
+ #### `deleteRecommendationClusters`
762
+
763
+ This API is used to delete the content of Recommendation Clusters.
764
+
765
+ > [!IMPORTANT]
766
+ > **Important:** Delete APIs should only be called when there is no content to publish. **Don't** call delete and publish APIs subsequently to replace the content as the publish APIs do that inherently. Reach out to [`engage-developers@google.com`](mailto:engage-developers@google.com) before using delete APIs.
767
+
768
+ ### Kotlin
769
+
770
+ client.deleteRecommendationClusters()
771
+
772
+ ### Java
773
+
774
+ client.deleteRecommendationClusters();
775
+
776
+ When the service receives the request, it removes the existing data from the
777
+ Recommendation Clusters. In case of an error, the entire request is rejected
778
+ and the existing state is maintained.
779
+
780
+ > [!NOTE]
781
+ > **Note:** This api is available from version 1.1.0 onwards.
782
+
783
+ #### `deleteFeaturedCluster`
784
+
785
+ This API is used to delete the content of Featured Cluster.
786
+
787
+ > [!IMPORTANT]
788
+ > **Important:** Delete APIs should only be called when there is no content to publish. **Don't** call delete and publish APIs subsequently to replace the content as the publish APIs do that inherently. Reach out to [`engage-developers@google.com`](mailto:engage-developers@google.com) before using delete APIs.
789
+
790
+ ### Kotlin
791
+
792
+ client.deleteFeaturedCluster()
793
+
794
+ ### Java
795
+
796
+ client.deleteFeaturedCluster();
797
+
798
+ When the service receives the request, it removes the existing data from the
799
+ Featured Cluster. In case of an error, the entire request is rejected
800
+ and the existing state is maintained.
801
+
802
+ > [!NOTE]
803
+ > **Note:** This api is available from version 1.1.0 onwards.
804
+
805
+ #### `deleteContinuationCluster`
806
+
807
+ This API is used to delete the content of Continuation Cluster.
808
+
809
+ > [!IMPORTANT]
810
+ > **Important:** Delete APIs should only be called when there is no content to publish. **Don't** call delete and publish APIs subsequently to replace the content as the publish APIs do that inherently. Reach out to [`engage-developers@google.com`](mailto:engage-developers@google.com) before using delete APIs.
811
+
812
+ ### Kotlin
813
+
814
+ client.deleteContinuationCluster()
815
+
816
+ ### Java
817
+
818
+ client.deleteContinuationCluster();
819
+
820
+ When the service receives the request, it removes the existing data from the
821
+ Continuation Cluster. In case of an error, the entire request is rejected
822
+ and the existing state is maintained.
823
+
824
+ > [!NOTE]
825
+ > **Note:** This api is available from version 1.1.0 onwards.
826
+
827
+ #### `deleteUserManagementCluster`
828
+
829
+ This API is used to delete the content of UserAccountManagement Cluster.
830
+
831
+ > [!IMPORTANT]
832
+ > **Important:** Delete APIs should only be called when there is no content to publish. **Don't** call delete and publish APIs subsequently to replace the content as the publish APIs do that inherently. Reach out to [`engage-developers@google.com`](mailto:engage-developers@google.com) before using delete APIs.
833
+
834
+ ### Kotlin
835
+
836
+ client.deleteUserManagementCluster()
837
+
838
+ ### Java
839
+
840
+ client.deleteUserManagementCluster();
841
+
842
+ When the service receives the request, it removes the existing data from the
843
+ UserAccountManagement Cluster. In case of an error, the entire request is
844
+ rejected and the existing state is maintained.
845
+
846
+ > [!NOTE]
847
+ > **Note:** This api is available from version 1.1.0 onwards.
848
+
849
+ #### `deleteClusters`
850
+
851
+ This API is used to delete the content of a given cluster type.
852
+
853
+ > [!IMPORTANT]
854
+ > **Important:** Delete APIs should only be called when there is no content to publish. **Don't** call delete and publish APIs subsequently to replace the content as the publish APIs do that inherently. Reach out to [`engage-developers@google.com`](mailto:engage-developers@google.com) before using delete APIs.
855
+
856
+ ### Kotlin
857
+
858
+ client.deleteClusters(
859
+ DeleteClustersRequest.Builder()
860
+ .addClusterType(ClusterType.TYPE_CONTINUATION)
861
+ .addClusterType(ClusterType.TYPE_FEATURED)
862
+ .addClusterType(ClusterType.TYPE_RECOMMENDATION)
863
+ .build())
864
+
865
+ ### Java
866
+
867
+ client.deleteClusters(
868
+ new DeleteClustersRequest.Builder()
869
+ .addClusterType(ClusterType.TYPE_CONTINUATION)
870
+ .addClusterType(ClusterType.TYPE_FEATURED)
871
+ .addClusterType(ClusterType.TYPE_RECOMMENDATION)
872
+ .build());
873
+
874
+ When the service receives the request, it removes the existing data from all
875
+ clusters matching the specified cluster types. Clients can choose to pass one or
876
+ many cluster types. In case of an error, the entire request is rejected and the
877
+ existing state is maintained.
878
+
879
+ #### Error handling
880
+
881
+ It is highly recommended to listen to the task result from the publish APIs such
882
+ that a follow-up action can be taken to recover and resubmit an successful task.
883
+
884
+ ### Kotlin
885
+
886
+ client.publishRecommendationClusters(
887
+ PublishRecommendationClustersRequest.Builder()
888
+ .addRecommendationCluster(..)
889
+ .build())
890
+ .addOnCompleteListener { task ->
891
+ if (task.isSuccessful) {
892
+ // do something
893
+ } else {
894
+ val exception = task.exception
895
+ if (exception is AppEngageException) {
896
+ @AppEngageErrorCode val errorCode = exception.errorCode
897
+ if (errorCode == AppEngageErrorCode.SERVICE_NOT_FOUND) {
898
+ // do something
899
+ }
900
+ }
901
+ }
902
+ }
903
+
904
+ ### Java
905
+
906
+ client.publishRecommendationClusters(
907
+ new PublishRecommendationClustersRequest.Builder()
908
+ .addRecommendationCluster(...)
909
+ .build())
910
+ .addOnCompleteListener(
911
+ task -> {
912
+ if (task.isSuccessful()) {
913
+ // do something
914
+ } else {
915
+ Exception exception = task.getException();
916
+ if (exception instanceof AppEngageException) {
917
+ @AppEngageErrorCode
918
+ int errorCode = ((AppEngageException) exception).getErrorCode();
919
+ if (errorCode == AppEngageErrorCode.SERVICE_NOT_FOUND) {
920
+ // do something
921
+ }
922
+ }
923
+ }
924
+ });
925
+
926
+ The error is returned as an `AppEngageException` with the cause included as an
927
+ error code.
928
+
929
+ | Error code | Error name | Note |
930
+ |---|---|---|
931
+ | `1` | `SERVICE_NOT_FOUND` | The service is not available on the given device. |
932
+ | `2` | `SERVICE_NOT_AVAILABLE` | The service is available on the given device, but it is not available at the time of the call (for example, it is explicitly disabled). |
933
+ | `3` | `SERVICE_CALL_EXECUTION_FAILURE` | The task execution failed due to threading issues. In this case, it can be retried. |
934
+ | `4` | `SERVICE_CALL_PERMISSION_DENIED` | The caller is not allowed to make the service call. |
935
+ | `5` | `SERVICE_CALL_INVALID_ARGUMENT` | The request contains invalid data (for example, more than the allowed number of clusters). |
936
+ | `6` | `SERVICE_CALL_INTERNAL` | There is an error on the service side. |
937
+ | `7` | `SERVICE_CALL_RESOURCE_EXHAUSTED` | The service call is made too frequently. |
938
+
939
+ ### Step 3: Handle broadcast intents
940
+
941
+ In addition to making publish content API calls through a job, it is also
942
+ required to set up a
943
+ [`BroadcastReceiver`](https://developer.android.com/reference/android/content/BroadcastReceiver) to receive
944
+ the request for a content publish.
945
+
946
+ The goal of broadcast intents is mainly for app reactivation and forcing data
947
+ sync. Broadcast intents are not designed to be sent very frequently. It is only
948
+ triggered when the Engage Service determines the content might be stale (for
949
+ example, a week old). That way, there is more confidence that the user can have
950
+ a fresh content experience, even if the application has not been executed for a
951
+ long period of time.
952
+
953
+ The `BroadcastReceiver` must be set up in the following two ways:
954
+
955
+ - Dynamically register an instance of the `BroadcastReceiver` class using
956
+ `Context.registerReceiver()`. This enables communication from applications
957
+ that are still live in memory.
958
+
959
+ ### Kotlin
960
+
961
+ class AppEngageBroadcastReceiver : BroadcastReceiver(){
962
+ // Trigger recommendation cluster publish when PUBLISH_RECOMMENDATION broadcast
963
+ // is received
964
+ // Trigger featured cluster publish when PUBLISH_FEATURED broadcast is received
965
+ // Trigger continuation cluster publish when PUBLISH_CONTINUATION broadcast is
966
+ // received
967
+ }
968
+
969
+ fun registerBroadcastReceivers(context: Context){
970
+ var context = context
971
+ context = context.applicationContext
972
+
973
+ // Register Recommendation Cluster Publish Intent
974
+ context.registerReceiver(AppEngageBroadcastReceiver(),
975
+ IntentFilter(Intents.ACTION_PUBLISH_RECOMMENDATION),
976
+ com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
977
+ /*scheduler=*/null)
978
+
979
+ // Register Featured Cluster Publish Intent
980
+ context.registerReceiver(AppEngageBroadcastReceiver(),
981
+ IntentFilter(Intents.ACTION_PUBLISH_FEATURED),
982
+ com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
983
+ /*scheduler=*/null)
984
+
985
+ // Register Continuation Cluster Publish Intent
986
+ context.registerReceiver(AppEngageBroadcastReceiver(),
987
+ IntentFilter(Intents.ACTION_PUBLISH_CONTINUATION),
988
+ com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
989
+ /*scheduler=*/null)
990
+ }
991
+
992
+ ### Java
993
+
994
+ class AppEngageBroadcastReceiver extends BroadcastReceiver {
995
+ // Trigger recommendation cluster publish when PUBLISH_RECOMMENDATION broadcast
996
+ // is received
997
+
998
+ // Trigger featured cluster publish when PUBLISH_FEATURED broadcast is received
999
+
1000
+ // Trigger continuation cluster publish when PUBLISH_CONTINUATION broadcast is
1001
+ // received
1002
+ }
1003
+
1004
+ public static void registerBroadcastReceivers(Context context) {
1005
+
1006
+ context = context.getApplicationContext();
1007
+
1008
+ // Register Recommendation Cluster Publish Intent
1009
+ context.registerReceiver(new AppEngageBroadcastReceiver(),
1010
+ new IntentFilter(com.google.android.engage.service.Intents. ACTION_PUBLISH_RECOMMENDATION),
1011
+ com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
1012
+ /*scheduler=*/null);
1013
+
1014
+ // Register Featured Cluster Publish Intent
1015
+ context.registerReceiver(new AppEngageBroadcastReceiver(),
1016
+ new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_FEATURED),
1017
+ com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
1018
+ /*scheduler=*/null);
1019
+
1020
+ // Register Continuation Cluster Publish Intent
1021
+ context.registerReceiver(new AppEngageBroadcastReceiver(),
1022
+ new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_CONTINUATION),
1023
+ com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
1024
+ /*scheduler=*/null);
1025
+
1026
+ }
1027
+
1028
+ - Statically declare an implementation with the `<receiver>` tag in your
1029
+ `AndroidManifest.xml` file. This allows the application to receive broadcast
1030
+ intents when it is not running, and also allows the application to publish
1031
+ the content.
1032
+
1033
+ <application>
1034
+ <receiver
1035
+ android:name=".AppEngageBroadcastReceiver"
1036
+ android:permission="com.google.android.engage.REQUEST_ENGAGE_DATA"
1037
+ android:exported="true"
1038
+ android:enabled="true">
1039
+ <intent-filter>
1040
+ <action android:name="com.google.android.engage.action.PUBLISH_RECOMMENDATION" />
1041
+ </intent-filter>
1042
+ <intent-filter>
1043
+ <action android:name="com.google.android.engage.action.PUBLISH_FEATURED" />
1044
+ </intent-filter>
1045
+ <intent-filter>
1046
+ <action android:name="com.google.android.engage.action.PUBLISH_CONTINUATION" />
1047
+ </intent-filter>
1048
+ </receiver>
1049
+ </application>
1050
+
1051
+ The following [intents](https://developer.android.com/reference/android/content/Intent) is sent by the
1052
+ service:
1053
+
1054
+ - `com.google.android.engage.action.PUBLISH_RECOMMENDATION` It is recommended to start a `publishRecommendationClusters` call when receiving this intent.
1055
+ - `com.google.android.engage.action.PUBLISH_FEATURED` It is recommended to start a `publishFeaturedCluster` call when receiving this intent.
1056
+ - `com.google.android.engage.action.PUBLISH_CONTINUATION` It is recommended to start a `publishContinuationCluster` call when receiving this intent.
1057
+
1058
+ ## Integration workflow
1059
+
1060
+ For a step-by-step guide on verifying your integration after it is complete, see
1061
+ [Engage developer integration workflow](https://developer.android.com/guide/playcore/engage/workflow).
1062
+
1063
+ ## FAQs
1064
+
1065
+ See [Engage SDK Frequently Asked Questions](https://developer.android.com/guide/playcore/engage/faq) for
1066
+ FAQs.
1067
+
1068
+ ## Contact
1069
+
1070
+ Contact
1071
+ [`engage-developers@google.com`](mailto:engage-developers@google.com) if there are
1072
+ any questions during the integration process.
1073
+
1074
+ ## Next steps
1075
+
1076
+ After completing this integration, your next steps are as follows:
1077
+
1078
+ - Send an email to [`engage-developers@google.com`](mailto:engage-developers@google.com) and attach your integrated APK that is ready for testing by Google.
1079
+ - Google performs a verification and reviews internally to make sure the integration works as expected. If changes are needed, Google contacts you with any necessary details.
1080
+ - When testing is complete and no changes are needed, Google contacts you to notify you that you can start publishing the updated and integrated APK to the Play Store.
1081
+ - After Google has confirmed that your updated APK has been published to the Play Store, your **Recommendation** , **Featured** , and **Continuation** clusters may be published and visible to users.