Chia sẻ Quyền trong ứng dụng với Google TV bằng Engage SDK

Hướng dẫn này cung cấp cho nhà phát triển hướng dẫn về cách chia sẻ dữ liệu về quyền và gói thuê bao ứng dụng với Google TV bằng Engage SDK. Người dùng có thể tìm thấy nội dung mà họ có quyền xem và cho phép Google TV đưa ra các đề xuất nội dung có liên quan cao cho người dùng ngay trong trải nghiệm Google TV trên TV, thiết bị di động và máy tính bảng.

Điều kiện tiên quyết

Bạn phải thiết lập nguồn cấp dữ liệu hành động đa phương tiện thì mới có thể sử dụng API quyền trên thiết bị. Nếu bạn chưa hoàn tất, hãy hoàn tất quy trình làm quen với nguồn cấp dữ liệu hành động đối với nội dung đa phương tiện.

Chuẩn bị trước

Trước khi bắt đầu, hãy hoàn thành các bước sau: xác minh rằng ứng dụng của bạn nhắm đến API cấp 19 trở lên để tích hợp

  1. Thêm thư viện com.google.android.engage vào ứng dụng của bạn:

    Có các SDK riêng biệt để sử dụng trong quá trình tích hợp: một SDK cho ứng dụng di động và một SDK cho ứng dụng TV.

    Đối với thiết bị di động

    
      dependencies {
        implementation 'com.google.android.engage:engage-core:1.5.5
      }
    

    cho TV

    
      dependencies {
        implementation 'com.google.android.engage:engage-tv:1.0.2
      }
    
  2. Đặt môi trường dịch vụ Engage thành môi trường phát hành chính thức trong tệp AndroidManifest.xml.

    Đối với tệp APK dành cho thiết bị di động

    
    <meta-data
          android:name="com.google.android.engage.service.ENV"
          android:value="PRODUCTION">
    </meta-data>
    

    Đối với tệp APK dành cho TV

    
    <meta-data
        android:name="com.google.android.engage.service.ENV"
        android:value="PRODUCTION">
    </meta-data>
    
  3. Trước khi gửi tệp APK đến Google, hãy đặt môi trường dịch vụ Engage thành môi trường phát hành chính thức trong tệp AndroidManifest.xml. Để đạt được hiệu suất tối ưu và khả năng tương thích trong tương lai, chỉ phát hành dữ liệu khi ứng dụng chạy ở nền trước và người dùng đang tích cực tương tác với ứng dụng, chẳng hạn như khi khởi chạy ứng dụng, sau khi đăng nhập hoặc trong khi sử dụng. Không nên phát hành từ các quy trình ở chế độ nền.

  4. Xuất bản thông tin về gói thuê bao trên các sự kiện sau:

    1. Người dùng đăng nhập vào ứng dụng của bạn.
    2. Người dùng chuyển đổi giữa các hồ sơ (nếu hồ sơ được hỗ trợ).
    3. Người dùng mua một gói thuê bao mới.
    4. Người dùng nâng cấp gói thuê bao hiện có.
    5. Gói thuê bao của người dùng hết hạn.

Tích hợp

Phần này cung cấp các ví dụ và hướng dẫn về mã cần thiết để triển khai AccountProfileSubscriptionEntity nhằm quản lý nhiều loại gói thuê bao.

Tài khoản và hồ sơ người dùng

Để cho phép sử dụng các tính năng được cá nhân hoá trên Google TV, hãy cung cấp thông tin tài khoản. Sử dụng AccountProfile để cung cấp:

  1. Mã tài khoản: Giá trị nhận dạng duy nhất đại diện cho tài khoản của người dùng. Đây có thể là mã tài khoản thực tế hoặc phiên bản được làm rối mã nguồn một cách thích hợp.
// Set the account ID to which the subscription applies.
// Don't set the profile ID because subscription applies to account level.
val accountProfile = AccountProfile.Builder()
  .setAccountId("user_account_id")
  .setProfileId("user_profile id")
  .build();

Gói thuê bao hạng phổ thông

Đối với người dùng có gói thuê bao cơ bản của các dịch vụ nhà cung cấp nội dung nghe nhìn (ví dụ: một dịch vụ có một cấp thuê bao cấp quyền truy cập vào tất cả nội dung có tính phí), hãy cung cấp những thông tin chi tiết thiết yếu sau:

  1. Loại gói thuê bao: Nêu rõ gói thuê bao cụ thể mà người dùng có.

    1. SUBSCRIPTION_TYPE_ACTIVE: Người dùng có gói thuê bao có tính phí đang hoạt động.
    2. SUBSCRIPTION_TYPE_ACTIVE_TRIAL: Người dùng có gói thuê bao dùng thử.
    3. SUBSCRIPTION_TYPE_INACTIVE: Người dùng có tài khoản nhưng không có gói thuê bao hoặc gói dùng thử đang hoạt động.
  2. Thời gian hết hạn: Thời gian không bắt buộc tính bằng mili giây. Chỉ định thời điểm gói thuê bao hết hạn.

  3. Tên gói của nhà cung cấp: Chỉ định tên gói của ứng dụng xử lý gói thuê bao.

Ví dụ về nguồn cấp dữ liệu mẫu của nhà cung cấp nội dung nghe nhìn.

"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
  }

Ví dụ sau đây tạo một SubscriptionEntity cho người dùng:

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();

Gói thuê bao trả phí

Nếu ứng dụng cung cấp các gói thuê bao cao cấp nhiều cấp, bao gồm nội dung hoặc tính năng mở rộng ngoài cấp thông thường, hãy thể hiện điều này bằng cách thêm một hoặc nhiều quyền vào Gói thuê bao.

Quyền này có các trường sau:

  1. Giá trị nhận dạng: Chuỗi giá trị nhận dạng bắt buộc cho quyền này. Mã này phải khớp với một trong các mã nhận dạng quyền (lưu ý rằng đây không phải là trường mã nhận dạng) được cung cấp trong nguồn cấp dữ liệu của nhà cung cấp nội dung đa phương tiện được phát hành trên Google TV.
  2. Tên: Đây là thông tin phụ trợ và được dùng để so khớp quyền. Mặc dù không bắt buộc, nhưng việc cung cấp tên quyền mà con người có thể đọc được sẽ giúp cả nhà phát triển và nhóm hỗ trợ hiểu rõ hơn về quyền của người dùng. Ví dụ: Sling Orange.
  3. Expiration TimeMillis: Chỉ định thời gian hết hạn theo mili giây cho quyền này (không bắt buộc) nếu thời gian này khác với thời gian hết hạn của gói thuê bao. Theo mặc định, quyền này sẽ hết hạn khi gói thuê bao hết hạn.

Đối với đoạn mã nguồn cấp dữ liệu của nhà cung cấp nội dung nghe nhìn mẫu sau đây:

"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"
  }

Ví dụ sau đây tạo một SubscriptionEntity cho người dùng đã đăng ký:

// 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();

Gói thuê bao của dịch vụ được liên kết

Mặc dù các gói thuê bao thường thuộc về nhà cung cấp nội dung đa phương tiện của ứng dụng ban đầu, nhưng bạn có thể phân bổ một gói thuê bao cho một gói dịch vụ được liên kết bằng cách chỉ định tên gói dịch vụ được liên kết trong gói thuê bao.

Mã mẫu sau đây minh hoạ cách tạo gói thuê bao của người dùng.

// 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();

Ngoài ra, nếu người dùng có một gói thuê bao khác cho một dịch vụ phụ, hãy thêm một gói thuê bao khác và đặt tên gói dịch vụ được liên kết cho phù hợp.

// Subscription for linked service package
val linkedSubscription = Subscription
  .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();

Nếu muốn, bạn cũng có thể thêm quyền vào gói thuê bao dịch vụ được liên kết.

Cung cấp nhóm gói thuê bao

Chạy công việc phát hành nội dung trong khi ứng dụng đang chạy ở nền trước.

Sử dụng phương thức publishSubscriptionCluster(), từ lớp AppEngagePublishClient, để phát hành đối tượng SubscriptionCluster.

Sử dụng isServiceAvailable để kiểm tra xem dịch vụ có thể tích hợp hay không.

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

Sử dụng setSubscription() để xác minh rằng người dùng chỉ có một gói thuê bao dịch vụ.

Sử dụng addLinkedSubscription() hoặc addLinkedSubscriptions() để chấp nhận danh sách các gói thuê bao được liên kết, cho phép người dùng có từ 0 đến nhiều gói thuê bao được liên kết.

Khi dịch vụ nhận được yêu cầu, một mục mới sẽ được tạo và mục cũ sẽ tự động bị xoá sau 60 ngày. Hệ thống luôn sử dụng mục nhập mới nhất. Trong trường hợp xảy ra lỗi, toàn bộ yêu cầu sẽ bị từ chối và trạng thái hiện tại sẽ được duy trì.

Cập nhật gói thuê bao

  1. Để cung cấp thông tin cập nhật ngay lập tức khi có thay đổi, hãy gọi publishSubscriptionCluster() bất cứ khi nào trạng thái gói thuê bao của người dùng thay đổi, chẳng hạn như kích hoạt, huỷ kích hoạt, nâng cấp, hạ cấp.
  2. Để thường xuyên xác thực độ chính xác, hãy gọi publishSubscriptionCluster() ít nhất một lần mỗi tháng.

  3. Để xoá dữ liệu Khám phá video, hãy xoá dữ liệu của người dùng theo cách thủ công khỏi máy chủ Google TV trước khoảng thời gian lưu giữ tiêu chuẩn là 60 ngày bằng phương thức client.deleteClusters(). Thao tác này sẽ xoá tất cả dữ liệu hiện có về việc khám phá video cho hồ sơ tài khoản hoặc cho toàn bộ tài khoản, tuỳ thuộc vào DeleteReason đã cho.

    Đoạn mã để xoá gói thuê bao của người dùng

      // If the user logs out from your media app, you must make the following call
      // to remove subscription and other video discovery data from the current
      // google TV device.
      client.deleteClusters(
        new DeleteClustersRequest.Builder()
          .setAccountProfile(
            AccountProfile
              .Builder()
              .setAccountId()
              .setProfileId()
              .build()
          )
        .setReason(DeleteReason.DELETE_REASON_USER_LOG_OUT)
        .build()
        )
      ```
    Following code snippet demonstrates removal of user subscription
    when user revokes the consent.
    
    ```Kotlin
      // If the user revokes the consent to share across device, make the call
      // to remove subscription and other video discovery data from all google
      // TV devices.
      client.deleteClusters(
        new DeleteClustersRequest.Builder()
          .setAccountProfile(
            AccountProfile
            .Builder()
            .setAccountId()
            .setProfileId()
            .build()
          )
          .setReason(DeleteReason.DELETE_REASON_LOSS_OF_CONSENT)
          .build()
      )
      ```
    
    Following code demonstrates how to remove subscription data on user profile
    deletion.
    
    ```Kotlin
    // If the user delete a specific profile, you must make the following call
    // to remove subscription data and other video discovery data.
    client.deleteClusters(
      new DeleteClustersRequest.Builder()
      .setAccountProfile(
        AccountProfile
        .Builder()
        .setAccountId()
        .setProfileId()
        .build()
      )
      .setReason(DeleteReason.DELETE_REASON_ACCOUNT_PROFILE_DELETION)
      .build()
    )
    

Thử nghiệm

Phần này cung cấp hướng dẫn từng bước để kiểm thử việc triển khai gói thuê bao. Xác minh độ chính xác của dữ liệu và chức năng phù hợp trước khi ra mắt.

Xuất bản danh sách kiểm tra tích hợp

  1. Quá trình phát hành sẽ diễn ra khi ứng dụng chạy ở nền trước và người dùng đang tích cực tương tác với ứng dụng.

  2. Xuất bản khi:

    • Người dùng đăng nhập lần đầu tiên.
    • Người dùng thay đổi hồ sơ (nếu hồ sơ được hỗ trợ).
    • Người dùng mua gói thuê bao mới.
    • Người dùng nâng cấp gói thuê bao.
    • Gói thuê bao của người dùng hết hạn.
  3. Kiểm tra xem ứng dụng có gọi đúng API isServiceAvailable()publishClusters() trong logcat trên các sự kiện phát hành hay không.

  4. Xác minh rằng dữ liệu hiển thị trong ứng dụng xác minh. Ứng dụng xác minh sẽ hiển thị gói thuê bao dưới dạng một hàng riêng biệt. Khi API phát hành được gọi, dữ liệu sẽ xuất hiện trong ứng dụng xác minh.

    • Xác minh rằng Cờ dịch vụ tương tác KHÔNG được đặt thành phiên bản chính thức trong tệp kê khai Android của ứng dụng.
    • Cài đặt và mở ứng dụng Engage Verification.
    • Nếu giá trị của isServiceAvailablefalse trong ứng dụng xác minh, hãy nhấp vào nút Toggle trong ứng dụng xác minh để đặt giá trị này thành true.
    • Nhập tên gói của ứng dụng. Tên gói sẽ tự động hiển thị dữ liệu đã xuất bản.
  5. Chuyển đến ứng dụng và thực hiện từng hành động sau:

    • Đăng nhập.
    • chuyển đổi giữa các hồ sơ (nếu được hỗ trợ).
    • Mua gói thuê bao mới.
    • Nâng cấp gói thuê bao hiện có.
    • Hết hạn gói thuê bao.

Xác minh chế độ tích hợp

Để kiểm thử quá trình tích hợp, hãy sử dụng ứng dụng xác minh.

Ứng dụng xác minh là một ứng dụng Android mà nhà phát triển có thể dùng để xác minh rằng SDK tích hợp đang hoạt động. Ứng dụng này có những chức năng giúp nhà phát triển xác minh dữ liệu và ý định truyền tin. Điều này giúp xác minh độ chính xác của dữ liệu và chức năng phù hợp trước khi phát hành.

  1. Đối với từng sự kiện, hãy kiểm tra xem ứng dụng có gọi API publishSubscription hay không. Xác minh dữ liệu đã xuất bản trong ứng dụng xác minh. Xác minh rằng mọi thứ đều có màu xanh lục trong ứng dụng xác minh
  2. Nếu tất cả thông tin của thực thể đều chính xác, thì bạn sẽ thấy dấu kiểm màu xanh lục "Đã hoàn tất" trong tất cả các thực thể.

    Ảnh chụp màn hình xác minh thành công ứng dụng
    Hình 1. Đã đăng ký thành công
  3. Các vấn đề cũng được làm nổi bật trong ứng dụng xác minh

    Ảnh chụp màn hình lỗi ứng dụng xác minh
    Hình 2.Không đăng ký được
  4. Để xem các vấn đề trong gói thuê bao, hãy dùng điều khiển từ xa của TV để lấy tiêu điểm vào gói thuê bao cụ thể đó rồi nhấp để xem các vấn đề. Trước tiên, bạn có thể phải đặt tiêu điểm vào hàng rồi di chuyển sang phải để tìm thẻ Gói thuê bao đi kèm. Các vấn đề được đánh dấu bằng màu đỏ như trong Hình 3. Ngoài ra, hãy dùng điều khiển từ xa để di chuyển xuống để xem các vấn đề về quyền trong gói thuê bao

    Ảnh chụp màn hình thông tin chi tiết về lỗi xác minh ứng dụng
    Hình 3.Lỗi về gói thuê bao
  5. Để xem các vấn đề trong quyền, hãy sử dụng điều khiển từ xa của TV để tập trung vào quyền cụ thể đó rồi nhấp để xem các vấn đề. Các vấn đề được làm nổi bật bằng màu đỏ.

    Ảnh chụp màn hình lỗi ứng dụng xác minh
    Hình 4.Thông tin chi tiết về lỗi gói thuê bao