Generated banner for Engage SDK Integration
Generated logo for Engage SDK Integration

Engage SDK Integration

Android (Google)OfficialCreated by Google LLCDistributed by Android (Google)

  • Skill
  • Tool integration
  • Software development
  • Apache-2.0
  • No issues found

From the author

Helps developers integrate, debug, and resolve Play Engage SDK implementation issues. Use when adding Engage SDK support, generating publishing code, mapping data classes to entities, or fixing SDK-related errors.
— the description by Google LLC

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a structured workflow for Android developers to integrate the Play Engage SDK. It covers the end-to-end process, including identifying vertical-specific requirements, generating necessary boilerplate code, mapping local data models to Engage entities, and configuring broadcast receivers for data synchronization. The skill also includes a verification checklist and troubleshooting guidance to ensure a robust implementation.

What it does

  • Guides developers through vertical-specific Engage SDK integration steps.
  • Generates boilerplate code for constants, entity converters, request factories, and workers.
  • Assists in mapping local app models to required Engage entity schemas.
  • Provides instructions for both static and dynamic broadcast receiver registration.
  • Offers a self-verification checklist to ensure successful implementation.
  • Provides troubleshooting steps for common compilation and integration errors.

When to use it

  • When adding Play Engage SDK support to an Android application.
  • When generating publishing code for recommendation or continuation clusters.
  • When mapping existing local data classes to Engage-compatible entities.
  • When debugging SDK-related errors or implementation issues.

Advantages

  • Ensures adherence to mandatory SDK structure and entity requirements.
  • Reduces manual effort by providing standardized code templates.
  • Promotes best practices for background data synchronization.
  • Simplifies the complex process of vertical-specific configuration.

Usage examples

“How do I integrate the Engage SDK for my food delivery app?”
The agent will identify the food vertical, guide you through selecting the appropriate cluster types, and generate the required boilerplate classes like ItemToEntityConverter and EngageWorker.
“I am getting a background execution error with my broadcast receiver. How do I fix it?”
The agent will instruct you to implement dynamic registration for your EngageBroadcastReceiver and verify that the correct permissions are handled.
“How do I map my local restaurant data class to a StoreEntity?”
The agent will analyze your data class, compare it against the food schema, and generate the conversion logic for your ItemToEntityConverter.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/android/engage-sdk-integration/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip engage-sdk-integration.zip -d .agents/skills

Documentation by Google LLC

This skill guides you through integrating the Play Engage SDK into an Android app. It ensures that the code follows the mandatory structure and uses the required Engage entities for each vertical.

Workflow

Follow these steps to assist the developer:

  1. Identify vertical and cluster:

    • Ask the developer which vertical their app belongs to based on references/schemas/.

    • Check if the integration is for TV or mobile. If the integration is for TV, read the TV-specific sections in patterns.md as well.

    • Use {VERTICAL}.md in the references/schemas/ directory to identify the corresponding Engage entities and the client class name. The client field in the JSON provides the full class name. For example, com.google.android.engage.food.service.AppEngageFoodClient.

    • Note: Initializing the client class requires a Context parameter. For example, AppEngageFoodClient(context).

    • Always refer to common.md for common entities.

    • Ask which cluster type they want to publish from the supported cluster types for that vertical.

    • Find the method to call from {VERTICAL}.md in the references/schemas/ directory for the specified cluster. Each method will specify the request it expects.

    • Get the request structure from requests.md and clusters from clusters.md. Then suggest and use sources to fill the fields in the request structure correctly, along with the required entities and clusters.

  2. Generate structured boilerplate code:

    • Create a new directory for all Engage-related code. Name the directory to match the naming convention of the existing codebase.

    • Generate the following classes using templates in patterns.md:

      • Constants: holds constant values such as attempt counts and publish types.

      • ItemToEntityConverter: converts the app's local models to Engage's Entity models.

      • ClusterRequestFactory: constructs the publish requests.

      • EngageWorker: handles the actual publishing and publish errors using WorkManager.

      • EngagePublisher: orchestrates periodic and one-time jobs.

      • EngageBroadcastReceiver: listens for AppEngageService intents and starts a one-time publish job from EngagePublisher. Important : Implement both static registration and dynamic registration patterns, including the companion object register method inside the EngageBroadcastReceiver class.

  3. Suggest entity mapping:

    • Ask the developer to provide their local model schema (for example, a data class or a JSON snippet).

    • If they haven't provided one, share entities from {VERTICAL}.md in the references/schemas/ directory as a guide.

    • Once the local model is identified, suggest a mapping to the corresponding Engage entity.

    • Generate the conversion logic using the ItemToEntityConverter pattern in patterns.md and add it to the generated {ENGAGE_CODE_DIR}/ItemToEntityConverter.

  4. Suggest data source:

    • Ask the developer to provide the source of actual data you'll publish.

    • Once you identify the data source, use it to fetch the data in the app's local model schema.

    • Use {ENGAGE_CODE_DIR}/ItemToEntityConverter to convert this data to an Engage entity.

    • Use obtained Engage entity model data with {ENGAGE_CODE_DIR}/ ClusterRequestFactory to get cluster requests.

    • Call corresponding cluster publishing method obtained from {VERTICAL}.md in the references/schemas/ directory with the obtained request in previous step in {ENGAGE_CODE_DIR}/EngageWorker.

  5. Gradle and manifest updates:

    • Suggest updates to build.gradle and AndroidManifest.xml.

    • For mobile apps, use patterns.md.

    • For TV apps, use the TV-specific sections in patterns.md.

    • Provide the necessary implementation dependencies for build.gradle or build.gradle.kts from patterns.md.

    • Provide the <receiver> and <service> declarations for AndroidManifest.xml.

    • Note: Except for TV, there aren't any vertical-specific imports. For all other verticals, com.google.android.engage:engage-core:1.6.0 is sufficient.

  6. Debugging and verification:

    • Self-verification checklist : Before considering your work complete, you must verify that you've implemented all of the following:

      • [ ] Registered EngageBroadcastReceiver statically in AndroidManifest.xml (inside the <application> tag).

      • [ ] Registered EngageBroadcastReceiver dynamically by calling EngageBroadcastReceiver.register(context) in the Application class or main Activity class.

      • [ ] Implemented the register method in EngageBroadcastReceiver's companion object to handle dynamic registration.

      • [ ] Handled empty data lists in EngageWorker (for example, by deleting the cluster instead of publishing empty data).

    • Perform a Gradle sync.

    • If errors occur (such as import failures, namespace conflicts, or compile errors), read references/troubleshooting.md to resolve them.

    • Execute a Gradle compilation (./gradlew compileDebugUnitTestSources or ./gradlew assembleDebug). See references/troubleshooting.md for compile rules and warnings about fast-compilation shortcuts. Repeat this step until compilation is successful.

  7. User checklist: At the end of code generation, notify the user to go through this checklist to verify that the integration is complete and as intended:

    • [ ] Verify that all the Engage-related files are created in {ENGAGE_CODE_DIR}/:

      • Constants

      • ItemToEntityConverter

      • ClusterRequestFactory

      • EngageWorker

      • {cluster_type}Publisher

      • EngageBroadcastReceiver

    • [ ] Verify that app's local model is converted to Engage entity by populating the fields correctly in the model in {ENGAGE_CODE_DIR}/ItemToEntityConverter.

    • [ ] Verify that all image URIs in ItemToEntityConverter point to images matching the strict aspect ratio requirements of the vertical (for example, 16:9, 1:1, 2:3).

    • [ ] Verify that {ENGAGE_CODE_DIR}/EngageWorker uses the data source identified in Step 4.

    • [ ] Verify that EngageBroadcastReceiver.register(context) is called within the Application class or MainActivity to register the receiver dynamically.

    • [ ] Verify that AndroidManifest.xml contains the static <receiver> declaration for EngageBroadcastReceiver with the necessary intent actions.

    • Important : Explicitly instruct the developer to call EngageBroadcastReceiver.register(context) inside their custom Application class onCreate() (or their main activity onCreate()) to dynamically register the receiver. Stress that both static and dynamic registrations are required for the integration to function.

Reference materials

Files

references/android/guide/playcore/engage/tv/entitlements.md

This guide contains instructions for developers to share app subscription and entitlement data with Google TV using Engage SDK. Users can find content they are entitled to and enable Google TV to deliver highly relevant content recommendations to users, directly within Google TV experiences on TV, mobile, and tablet.

Prerequisites

[!IMPORTANT] Important: Express interest in developing with Engage.

Onboarding the media actions feed is required before you can use the device entitlement API. If you haven't already done so, complete the media actions feed onboarding process.

Pre-work

Complete the Pre-work instructions in the Getting Started guide.

  1. Publish subscription information on the following events:

    1. User logs in to your app.

    2. User switches between profiles (if profiles are supported).

    3. User purchases a new subscription.

    4. User upgrades an existing subscription.

    5. User subscription expires.

Integration

This section provides the necessary code examples and instructions for implementing SubscriptionEntity to manage various subscription types.

Common tier subscription

For users with basic subscriptions to media provider services, for example, a service that has one subscription tier that grants access to all the paid content, provide these essential details:

  1. SubscriptionType: Clearly indicate the specific subscription plan the user has.

    • SUBSCRIPTION_TYPE_ACTIVE: User has an active paid subscription.

    • SUBSCRIPTION_TYPE_ACTIVE_TRIAL: User has a trial subscription.

    • SUBSCRIPTION_TYPE_INACTIVE: User has an account but no active subscription or trial.

    [!IMPORTANT] Important: Only users with SUBSCRIPTION_TYPE_ACTIVE or SUBSCRIPTION_TYPE_ACTIVE_TRIAL are eligible for personalized content recommendations based on their subscription.

  2. ExpirationTimeMillis: Optional time in milliseconds. Specify when the subscription is set to expire.

  3. ProviderPackageName: Specify the package name of the app that handles the subscription.

Example for the sample media provider feed.

"actionAccessibilityRequirement": [
  {
    "@type": "ActionAccessSpecification",
    "category": "subscription",
    "availabilityStarts": "2022-06-01T07:00:00Z",
    "availabilityEnds": "2026-05-31T07:00:00Z",
    "requiresSubscription": {
    "@type": "MediaSubscription",
    // Don't match this string,
    // ID is only used to for reconciliation purpose
    "@id": "https://www.example.com/971bfc78-d13a-4419",
    // Don't match this, as name is only used for displaying purpose
    "name": "Basic common name",
    "commonTier": true
  }

The following example creates a SubscriptionEntity for a user:

val subscription = SubscriptionEntity.Builder()
  .setSubscriptionType(
    SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE
  )
  .setProviderPackageName("com.google.android.example")
  // Optional
  // December 30, 2025 12:00:00AM in milliseconds since epoch
  .setExpirationTimeMillis(1767052800000)
  .build()
Premium subscription

If app offer multi-tiered premium subscription packages, which includes expanded content or features beyond the common tier, represent this by adding one or more entitlements to Subscription.

This entitlement has the following fields:

  1. Identifier: Required identifier string for this entitlement. This must match one of the entitlement identifiers (note that this isn't the ID field) provided in the media provider's feed published to Google TV.

  2. Name: This is auxiliary information and is used for entitlement matching. While optional, providing a human readable entitlement name enhances understanding of user entitlements for both developers and support teams. For example: Sling Orange.

  3. ExpirationTimeMillis: Optionally specify the expiration time in milliseconds for this entitlement, if it differs from the subscription expiration time. By default, the entitlement will expire with the expiry of subscription.

For the following sample media provider feed snippet:

"actionAccessibilityRequirement": [
  {
    "@type": "ActionAccessSpecification",
    "category": "subscription",
    "availabilityStarts": "2022-06-01T07:00:00Z",
    "availabilityEnds": "2026-05-31T07:00:00Z",
    "requiresSubscription": {
    "@type": "MediaSubscription",
    // Don't match this string,
    // ID is only used to for reconciliation purpose
    "@id": "https://www.example.com/971bfc78-d13a-4419",

    // Don't match this, as name is only used for displaying purpose
    "name": "Example entitlement name",
    "commonTier": false,
    // match this identifier in your API. This is the crucial
    // entitlement identifier used for recommendation purpose.
    "identifier": "example.com:entitlementString1"
  }

The following example creates a SubscriptionEntity for a subscribed user:

// Subscription with entitlements.
// The entitlement expires at the same time as its subscription.
val subscription = SubscriptionEntity.Builder()
  .setSubscriptionType(
    SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE
  )
  .setProviderPackageName("com.google.android.example")
  // Optional
  // December 30, 2025 12:00:00AM in milliseconds
  .setExpirationTimeMillis(1767052800000)
  .addEntitlement(
    SubscriptionEntitlement.Builder()
    // matches with the identifier in media provider feed
    .setEntitlementId("example.com:entitlementString1")
    .setDisplayName("entitlement name1")
    .build()
  )
  .build()

// Subscription with entitlements
// The entitement has different expiration time from its subscription
val subscription = SubscriptionEntity.Builder()
  .setSubscriptionType(
    SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE
  )
  .setProviderPackageName("com.google.android.example")
  // Optional
  // December 30, 2025 12:00:00AM in milliseconds
  .setExpirationTimeMillis(1767052800000)
  .addEntitlement(
    SubscriptionEntitlement.Builder()
    .setEntitlementId("example.com:entitlementString1")
    .setDisplayName("entitlement name1")
    // You may set the expiration time for entitlement
    // December 15, 2025 10:00:00 AM in milliseconds
    .setExpirationTimeMillis(1765792800000)
    .build())
  .build()
Subscription for linked service package

While subscriptions typically belong to the originating app's media provider, a subscription can be attributed to a linked service package by specifying the linked service package name within the subscription.

Following code sample demonstrate how to create user subscription.

// Subscription for linked service package
val subscription = SubscriptionEntity.Builder()
  .setSubscriptionType(
    SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE
  )
  .setProviderPackageName("com.google.android.example")
  // Optional
  // December 30, 2025 12:00:00AM in milliseconds since epoch
  .setExpirationTimeMillis(1767052800000)
  .build()

In addition, if the user has another subscription to a subsidiary service, add another subscription and set the linked service package name accordingly.

// Subscription for linked service package
val linkedSubscription = SubscriptionEntity.Builder()
  .setSubscriptionType(
    SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE
  )
  .setProviderPackageName("linked service package name")
  // Optional
  // December 30, 2025 12:00:00AM in milliseconds since epoch
  .setExpirationTimeMillis(1767052800000)
  .addBundledSubscription(
    BundledSubscription.Builder()
      .setBundledSubscriptionProviderPackageName(
        "bundled-subscription-package-name"
      )
      .setSubscriptionType(SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE)
      .setExpirationTimeMillis(111)
      .addEntitlement(
        SubscriptionEntitlement.Builder()
        .setExpirationTimeMillis(111)
        .setDisplayName("Silver subscription")
        .setEntitlementId("subscription.tier.platinum")
        .build()
      )
      .build()
  )
  .build()

Optionally, add entitlements to a linked service subscription too.

Provide subscription set

Run the content publish job while the app is in the foreground.

Use the publishSubscriptionCluster() method, from the AppEngagePublishClient class, to publish a SubscriptionCluster object.

Make sure to initialize the client and check for service availability as described in the Getting Started guide.

client.publishSubscription(
  PublishSubscriptionRequest.Builder()
    .setAccountProfile(accountProfile)
    .setSubscription(subscription)
    .build()
)

Use setSubscription() to verify that user should have only one subscription to the service.

Use addLinkedSubscription(), or addLinkedSubscriptions() which accept a list of linked subscriptions, to enable user to have zero or more linked subscriptions.

When the service receives the request, a new entry is created and the old entry is automatically deleted after 60 days. The system always uses the latest entry. In case of an error, the entire request is rejected and the existing state is maintained.

Keep subscription up-to-date
  1. To provide immediate updates upon changes, call publishSubscriptionCluster whenever a user's subscription state changes like activation, deactivation, upgrades, downgrades.

  2. To provide regular validation for ongoing accuracy, call publishSubscriptionCluster at least once per month.

    [!NOTE] Note: As Google TV automatically deletes historical data beyond 60 days to safeguard user privacy, publishing user subscription data at least once per month verify the validity of data. Unlike publishContinuationCluster for continue watching data, don't set syncAcrossDevices flag, as subscription information is by default used to provide content across all devices.

  3. To delete the Engage data, manually delete a user's data from the Google TV server before the standard 60-day retention period, use the client.deleteClusters method. This deletes all existing Engage data for the account profile, or for the entire account depending on the given DeleteReason.

    The following code snippet shows how to remove a user subscription:

    // If the user logs out from your media app, you must make the following call
    // to remove subscription and other Engage data from the current
    // google TV device.
    client.deleteClusters(
      DeleteClustersRequest.Builder()
        .setAccountProfile(accountProfile)
        .setDeleteReason(DeleteReason.DELETE_REASON_USER_LOG_OUT)
        .build()
    )

    The following code snippet demonstrates removal of user subscription when user revokes the consent:

    // If the user revokes the consent to share across device, make the call
    // to remove subscription and other Engage data from all google
    // TV devices.
    client.deleteClusters(
      DeleteClustersRequest.Builder()
        .setAccountProfile(accountProfile)
        .setDeleteReason(DeleteReason.DELETE_REASON_LOSS_OF_CONSENT)
        .build()
    )

    Following code demonstrates how to remove subscription data on user profile deletion.

    // If the user delete a specific profile, you must make the following call
    // to remove subscription data and other Engage data.
    client.deleteClusters(
      DeleteClustersRequest.Builder()
        .setAccountProfile(accountProfile)
        .setDeleteReason(DeleteReason.DELETE_REASON_ACCOUNT_PROFILE_DELETION)
        .build()
    )
Testing

This section provides a step-by-step guide for testing subscription implementation. Verify data accuracy and proper functionality before launch.

Publish Integration checklist
  1. Publishing should happen when the app is in the foreground and user the actively interacting with it.

  2. Publish when:

    • User logs in for the first time.

    • User changes profile (if profiles are supported).

    • User purchases new subscription.

    • User upgrades subscription.

    • User subscription expires.

  3. Check if app is correctly calling isServiceAvailable and publishClusters APIs in logcat, on the publishing events.

  4. Verify that data is visible in the verification app. The verification app should display subscription as a separate row. When the publish API is invoked, the data should show up in the verification app.

    [!IMPORTANT] Important: Verify that the Engage Service Flag is not set to production.

  5. Go to app and perform each of the following actions:

    • Sign in.

    • Switch between profiles (if supported).

    • Purchase a new subscription.

    • Upgrade an existing subscription.

    • Expire the subscription.

Verify integration

To test your integration, use the verification app.

  1. For each of the events, check if app has invoked the publishSubscription API. Verify the published data in the verification app. Verify that everything is green in verification app

  2. If all the entity's information is correct, it shows an "All Good" green check in all entities.

    Image: Verification App Success Screenshot Figure 1. Successful subscription

  3. Problems are also highlighted in verification app

    Image: Verification App Error Screenshot **Figure 2.**Subscription unsuccessful

  4. To see the problems in the bundled subscription, use the TV remote to focus on that specific bundled subscription and click to see the problems. You might have to first focus on the row and move to the right to find Bundled Subscription card. The problems are highlighted as red as shown in Fig 3. Also, use the remote to move down to see problems in the entitlements within bundled subscription

    Image: Verification App Error Details Screenshot **Figure 3.**Subscription Errors

  5. To see the problems in the entitlement, use the TV remote to focus on that specific entitlement and click to see the problems. The problems are highlighted as red.

    Image: Verification App Error Screenshot **Figure 4.**Subscription Error Details

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
Google LLC
Publisher
Android (Google) (Official)
Distributed by
Android (Google)
Source
android/skills · play/engage-sdk-integration · commit bf68e2d
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE.txt)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Google LLC or Android (Google).

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download engage-sdk-integration.zip