- Kotlin 80.7%
- TypeScript 18.7%
- JavaScript 0.6%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Google TV's TvProvider content API doesn't exist on Fire OS, so configureSyncWorker previously retried forever on Fire TV devices without ever succeeding. Add platform detection (TvPlatform), fail fast with a dedicated exception instead of an infinite WorkManager retry loop, and expose platform/providerAvailable on getChannelStatus. Also add reportPlaybackActivity/addToWatchlist/removeFromWatchlist, wrapping Amazon's Fire TV Content Personalization SDK via reflection (no compile-time dependency on the proprietary SDK jar) so the plugin still builds and no-ops safely everywhere the SDK isn't present. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
| .github/workflows | ||
| .idea | ||
| android | ||
| src | ||
| .eslintrc.json | ||
| .gitignore | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| rollup.config.mjs | ||
| tsconfig.json | ||
| vitest.config.ts | ||
capacitor-android-tv-channel
Capacitor plugin for Android TV Home Screen Channels (androidx.tvprovider) and background periodic synchronization with androidx.work.WorkManager.
Allows your Android TV Capacitor application to publish and manage home screen recommendation rows (channels and content cards) and schedule automatic background synchronization directly from a remote JSON feed.
Features
- 📺 Android TV Channels & Programs: Create, update, and remove rows and cards on the Android TV launcher screen (
androidx.tvprovider). - 🔄 Periodic Background Sync: Built-in
WorkManagerbackground worker to periodically fetch a remote JSON feed and update channels without opening the app. - ⚡ Immediate Content Delivery: Automatically runs an initial one-time background job upon configuration to immediately display content cards.
- 🛡️ Anti-Duplication: Automatic clearing and atomic updates to ensure cards don't accumulate duplicates.
- 🌐 Web Mock Fallback: Safe stub implementations for Web/PWA, Tizen, and WebOS environments without runtime exceptions.
- 🚀 100% Kotlin Native Layer: Written in modern idiomatic Kotlin with null-safety and robust error handling.
Install
npm install capacitor-android-tv-channel
npx cap sync android
Android Permissions
The plugin automatically includes the required permissions in its AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Usage Examples
1. Automated Background Periodic Synchronization (Recommended)
Configures Android TV to poll your backend endpoint (e.g. every 6 hours) and populate cards automatically:
import { TvChannel } from 'capacitor-android-tv-channel';
await TvChannel.configureSyncWorker({
channelId: 'trending_videos',
channelName: 'Trending Now',
channelDescription: 'Most watched videos today',
appLinkUri: 'myapp://home',
syncUrl: 'https://api.example.com/tv/trending.json',
headers: {
'Authorization': 'Bearer YOUR_AUTH_TOKEN',
'X-App-Version': '1.0.0'
},
intervalHours: 6, // Minimum 1 hour
clearOldPrograms: true, // Avoid duplicate cards
maxItems: 30
});
2. Manual Channel & Program Management
You can also programmatically publish or clear programs directly from JavaScript:
import { TvChannel } from 'capacitor-android-tv-channel';
// 1. Create channel
await TvChannel.createChannel({
id: 'featured_channel',
name: 'Featured Movies',
description: 'Hand-picked movies for you',
appLinkUri: 'myapp://movies'
});
// 2. Publish program cards
await TvChannel.setPrograms({
channelId: 'featured_channel',
programs: [
{
id: 'movie_101',
channelId: 'featured_channel',
title: 'Cosmic Journey',
description: 'Sci-Fi • 2h 15m',
posterArtUri: 'https://cdn.example.com/posters/cosmic.jpg',
intentUri: 'myapp://watch?id=movie_101',
durationMillis: 8100000,
type: 'movie'
}
],
clearOld: true
});
3. Cleanup on User Logout
await TvChannel.cancelSyncWorker({
channelId: 'trending_videos',
clearPrograms: true // Clears recommendation cards from the TV screen
});
JSON Feed Format (syncUrl)
Your remote endpoint configured in syncUrl should return a JSON response matching either format:
Structure Format (Recommended)
{
"channel": {
"id": "trending_videos",
"name": "Trending Now"
},
"programs": [
{
"id": "vid_101",
"title": "Amazing Nature Highlights",
"description": "4K Ultra HD • 15 min",
"posterArtUri": "https://cdn.example.com/thumbnails/101.jpg",
"intentUri": "myapp://watch?v=vid_101",
"durationMillis": 900000,
"type": "clip"
}
]
}
Flat Array Format
[
{
"id": "vid_101",
"title": "Amazing Nature Highlights",
"description": "4K Ultra HD • 15 min",
"posterArtUri": "https://cdn.example.com/thumbnails/101.jpg",
"intentUri": "myapp://watch?v=vid_101",
"durationMillis": 900000,
"type": "clip"
}
]
Amazon Fire TV Support
Google TV's home-screen channels API (androidx.tvprovider, described above) does not exist on Amazon Fire OS — Fire TV has its own launcher and recommendation system. This plugin handles that gracefully:
- Google TV path:
createChannel/configureSyncWorker/etc. detect a missing TvProvider up front and fail cleanly instead of crashing.TvSyncWorker's background sync also stops retrying on devices without a TvProvider (e.g. Fire TV) instead of retrying forever. getChannelStatus()now also returnsplatform: 'google_tv' | 'fire_tv' | 'unknown'andproviderAvailable: boolean, so your app can branch on the detected platform.- Fire TV recommendations:
reportPlaybackActivity(),addToWatchlist(), andremoveFromWatchlist()call into Amazon's Content Personalization SDK on Fire TV devices, and resolve{ supported: false }as a no-op everywhere else. BothreportPlaybackActivityand the watchlist methods require aprofileId— an app-internal (obfuscated) identifier for the viewer profile, as required by Amazon's API alongside the content id.
Two things to know before relying on Fire TV support in production:
- The Amazon SDK jar is not bundled in this plugin, and shouldn't need to be bundled by your app either. Amazon's Content Personalization SDK is proprietary and can't be redistributed here, so the native implementation calls it via reflection (
Class.forName) rather than a compile-time dependency — the SDK classes are neverimported. Per Amazon's docs, the plugin declares<uses-library android:name="com.amazon.tv.developer.sdk.content" android:required="false">in its manifest, which means a real Fire TV device provides these classes on the app's classpath itself at runtime. Where the SDK isn't present (any non-Fire-TV device, or an emulator without it), reflection fails safely and these methods return{ success: false }rather than crashing. - Sending SDK events is not the same as appearing in Fire TV's UI. Real "Continue Watching" / recommendation carousels on the Fire TV home screen additionally require registering your app in Amazon's content-catalog integration and entitlement-sharing process (a partnership process handled through Amazon TAM, not something this plugin or your code alone can turn on).
API
createChannel(...)deleteChannel(...)setPrograms(...)clearPrograms(...)configureSyncWorker(...)cancelSyncWorker(...)syncNow(...)getChannelStatus(...)requestChannelBrowsable(...)reportPlaybackActivity(...)addToWatchlist(...)removeFromWatchlist(...)- Interfaces
- Type Aliases
Main plugin interface for managing Android TV Channels and periodic synchronization.
createChannel(...)
createChannel(options: TvChannelData) => any
Creates or updates a channel on the Android TV home screen.
| Param | Type |
|---|---|
options |
TvChannelData |
Returns: any
Since: 0.0.1
deleteChannel(...)
deleteChannel(options: { channelId: string; }) => any
Deletes a channel and all its programs from the Android TV home screen.
| Param | Type |
|---|---|
options |
{ channelId: string; } |
Returns: any
Since: 0.0.1
setPrograms(...)
setPrograms(options: { channelId: string; programs: TvProgramData[]; clearOld?: boolean; }) => any
Sets or updates program cards in a given channel.
| Param | Type |
|---|---|
options |
{ channelId: string; programs: {}; clearOld?: boolean; } |
Returns: any
Since: 0.0.1
clearPrograms(...)
clearPrograms(options: { channelId: string; }) => any
Removes all program cards from a given channel.
| Param | Type |
|---|---|
options |
{ channelId: string; } |
Returns: any
Since: 0.0.1
configureSyncWorker(...)
configureSyncWorker(options: SyncWorkerConfig) => any
Configures a periodic WorkManager background worker to automatically fetch
JSON feeds from syncUrl and update the channel, and triggers an immediate one-time sync.
| Param | Type |
|---|---|
options |
SyncWorkerConfig |
Returns: any
Since: 0.0.1
cancelSyncWorker(...)
cancelSyncWorker(options: { channelId: string; clearPrograms?: boolean; }) => any
Cancels the periodic background sync worker for a given channel and optionally clears its cards.
| Param | Type |
|---|---|
options |
{ channelId: string; clearPrograms?: boolean; } |
Returns: any
Since: 0.0.1
syncNow(...)
syncNow(options?: { channelId?: string | undefined; } | undefined) => any
Manually triggers an immediate one-time background sync task.
| Param | Type |
|---|---|
options |
{ channelId?: string; } |
Returns: any
Since: 0.0.1
getChannelStatus(...)
getChannelStatus(options: { channelId: string; }) => any
Returns current status and program count for a channel.
| Param | Type |
|---|---|
options |
{ channelId: string; } |
Returns: any
Since: 0.0.1
requestChannelBrowsable(...)
requestChannelBrowsable(options: { channelId: string; }) => any
Requests Android system to make the channel browsable/visible to the user.
| Param | Type |
|---|---|
options |
{ channelId: string; } |
Returns: any
Since: 0.0.1
reportPlaybackActivity(...)
reportPlaybackActivity(options: { contentId: string; profileId: string; positionMillis?: number; durationMillis?: number; state?: TvPlaybackState; }) => any
Reports playback progress to Amazon's Fire TV Content Personalization SDK.
profileId is an app-internal (obfuscated) identifier for the viewer profile, required
by Amazon's API alongside the content id. No-ops with { supported: false } on non-Fire-TV devices.
| Param | Type |
|---|---|
options |
{ contentId: string; profileId: string; positionMillis?: number; durationMillis?: number; state?: TvPlaybackState; } |
Returns: any
Since: 1.1.1
addToWatchlist(...)
addToWatchlist(options: { contentId: string; profileId: string; }) => any
Adds an item to the user's Fire TV watchlist.
profileId is an app-internal (obfuscated) identifier for the viewer profile, required
by Amazon's API alongside the content id. No-ops with { supported: false } on non-Fire-TV devices.
| Param | Type |
|---|---|
options |
{ contentId: string; profileId: string; } |
Returns: any
Since: 1.1.1
removeFromWatchlist(...)
removeFromWatchlist(options: { contentId: string; profileId: string; }) => any
Removes an item from the user's Fire TV watchlist.
profileId is an app-internal (obfuscated) identifier for the viewer profile, required
by Amazon's API alongside the content id. No-ops with { supported: false } on non-Fire-TV devices.
| Param | Type |
|---|---|
options |
{ contentId: string; profileId: string; } |
Returns: any
Since: 1.1.1
Interfaces
TvChannelData
Data required to create or configure a Channel on Android TV.
| Prop | Type | Description |
|---|---|---|
id |
string |
Unique identifier of the channel (corresponds to Android internalProviderId). |
name |
string |
Display name of the channel row on the Android TV home screen. |
description |
string |
Optional channel description. |
appLinkUri |
string |
Deep link URI opened when the user clicks on the channel header or logo (e.g. "myapp://channel/feed"). |
logoUri |
string |
Optional URL or drawable resource name for the channel logo. |
TvProgramData
Data representing a single content card (preview program) inside a channel.
| Prop | Type | Description |
|---|---|---|
id |
string |
Unique identifier of the program item (e.g. "video-12345"). |
channelId |
string |
Parent channel ID matching TvChannelData.id. |
title |
string |
Title shown on the program card. |
description |
string |
Subtitle or description text (e.g. "Author • 10k views"). |
posterArtUri |
string |
URL of the card's poster image / thumbnail. |
intentUri |
string |
Deep link URI opened when the user clicks this card (e.g. "myapp://watch?v=12345"). |
durationMillis |
number |
Duration in milliseconds (optional). |
type |
TvProgramType |
Program content type: clip, movie, episode, or track. Defaults to 'clip'. |
releaseDate |
string | number |
Release date (timestamp in ms or ISO-8601 string). |
itemCount |
number |
Number of items (e.g. playlist or episode count). |
SyncWorkerConfig
Options for configuring background periodic synchronization with WorkManager.
| Prop | Type | Description |
|---|---|---|
channelId |
string |
Channel ID to be synchronized. |
channelName |
string |
Display name of the channel. |
channelDescription |
string |
Optional channel description. |
appLinkUri |
string |
Deep link URI for channel header click. |
syncUrl |
string |
HTTP(S) endpoint URL returning JSON feed. |
headers |
Record<string, string> |
Optional custom HTTP headers (e.g. Authorization, X-Api-Key). |
intervalHours |
number |
Periodic sync interval in hours (default: 6, minimum Android WorkManager interval: 15 minutes / 1 hour recommended). |
clearOldPrograms |
boolean |
Whether to remove old programs before publishing new ones (default: true, prevents duplicates). |
maxItems |
number |
Maximum number of cards to display in the channel row (default: 30). |
TvChannelStatus
Current channel status on the device.
| Prop | Type | Description |
|---|---|---|
isCreated |
boolean |
Whether the channel has been registered in Android TvProvider. |
channelId |
number |
System row ID assigned by Android TvProvider (if created). |
isBrowsable |
boolean |
Whether the channel is currently visible/browsable on the home screen. |
programCount |
number |
Number of active programs in this channel. |
lastSyncTimestamp |
number |
Unix timestamp in milliseconds of the last successful background sync. |
platform |
'google_tv' | 'fire_tv' | 'unknown' |
Detected TV platform on this device. |
providerAvailable |
boolean |
Whether the Android TvProvider (content://android.media.tv) is available on this device. False on Fire TV and other devices without the Android TV Input Framework. |
Type Aliases
TvProgramType
Supported program types on Android TV Home screen.
'clip' | 'movie' | 'episode' | 'track'
TvPlaybackState
Playback state reported to Amazon's Fire TV Content Personalization SDK.
'playing' | 'paused' | 'exit' | 'interstitial'
License
MIT © MarcBanc