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
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 }
Đặ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>
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.
Xuất bản thông tin về gói thuê bao trên các sự kiện sau:
- Người dùng đăng nhập vào ứng dụng của bạn.
- Người dùng chuyển đổi giữa các hồ sơ (nếu hồ sơ được hỗ trợ).
- Người dùng mua một gói thuê bao mới.
- Người dùng nâng cấp gói thuê bao hiện có.
- 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 AccountProfile
và SubscriptionEntity
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:
- 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:
Loại gói thuê bao: Nêu rõ gói thuê bao cụ thể mà người dùng có.
SUBSCRIPTION_TYPE_ACTIVE
: Người dùng có gói thuê bao có tính phí đang hoạt động.SUBSCRIPTION_TYPE_ACTIVE_TRIAL
: Người dùng có gói thuê bao dùng thử.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.
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.
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:
- 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.
- 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.
- 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
- Để 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. Để 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.Để 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àoDeleteReason
đã 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
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.
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.
Kiểm tra xem ứng dụng có gọi đúng API
isServiceAvailable()
vàpublishClusters()
trong logcat trên các sự kiện phát hành hay không.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
isServiceAvailable
làfalse
trong ứng dụng xác minh, hãy nhấp vào nútToggle
trong ứng dụng xác minh để đặt giá trị này thànhtrue
. - 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.
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.
- Đố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 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ể.
Hình 1. Đã đăng ký thành công Các vấn đề cũng được làm nổi bật trong ứng dụng xác minh
Hình 2.Không đăng ký được Để 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
Hình 3.Lỗi về gói thuê bao Để 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 đỏ.
Hình 4.Thông tin chi tiết về lỗi gói thuê bao