Vegaヘッドレスタスクとヘッドレスサービス
JavaScript(JS)は、ヘッドレスタスクとヘッドレスサービスという2つの方法により、ユーザーインターフェイス(UI)を表示せずにバックグラウンドで実行することができます。タスクは独立して動作する1回限りの操作であるのに対し、サービスは継続的な対話を可能にします。たとえば、タスクでは、アプリを開かずにTVチャンネルデータを取得して番組ガイドを更新できます。サービスはメディア再生などの機能を処理します。UIはサービスにコマンド(再生や一時停止など)を送信でき、サービスはメディアのストリーミングと処理を別のランタイムで管理します。このアプローチにより、負荷の高い処理をバックグラウンドに移動して、メインインターフェイスの応答性を維持することができます。
ヘッドレスJSタスクおよびサービスのJSランタイム
ヘッドレスJSタスクとヘッドレスJSサービスは、バックグラウンドでVegaアプリコンポーネントを利用します。アプリコンポーネントは、JSコードの実行を可能にするために最上位にセカンダリJSランタイム(Hermesで動作)を追加し、コードからライフサイクルイベントをリッスンできるようにします。ヘッドレスJSタスク/サービスの各インスタンスには、それぞれ独自のJavaScriptランタイムインスタンスが保持されます。
ヘッドレスJSコンテキストでサポートされるモジュール
ヘッドレスランタイムは、メモリフットプリントを小さく保つために、ユーザーインターフェイスで利用できる機能を簡易化したものです。次の表に示すモジュールのみがサポートされます。
| モジュール | 注記 |
|---|---|
| ログ | console.log |
| ネットワーク | fetch |
| タイマー | |
| Promise | |
| プラットフォーム | インポートには'@amazon-devices/react-native-kepler/Libraries/Utilities/Platform'を使用してください。import Platform from '@amazon-devices/react-native-kepler/Libraries/Utilities/Platform'; |
| パフォーマンス | global.performance.now |
ComponentInstanceManager |
インポートには'@amazon-devices/react-native-kepler/Libraries/ComponentInstance/ComponentInstanceManager'を使用してください。import { ComponentType, type IComponentInstance } from '@amazon-devices/react-native-kepler/Libraries/ComponentInstance/ComponentInstanceManager'; |
FileReader |
インポートには'@amazon-devices/react-native-kepler/Libraries/Blob/FileReader'を使用してください。import FileReader from '@amazon-devices/react-native-kepler/Libraries/Blob/FileReader'; |
URLSearchParams |
インポートには'@amazon-devices/react-native-kepler/Libraries/Blob/URL'を使用してください。import {URLSearchParams} from '@amazon-devices/react-native-kepler/Libraries/Blob/URL'; |
I18nManager |
インポートには'@amazon-devices/react-native-kepler/Libraries/ReactNative/I18nManager'を使用してください。import {I18nManager} from '@amazon-devices/react-native-kepler/Libraries/ReactNative/I18nManager'; |
ヘッドレスJSコンテキストでサポートされるReact Nativeライブラリ
ヘッドレスJSランタイムでサポートされるモジュールは限られており、次の表に示す特定のReact Nativeライブラリのセットのみがサポートされます。
| ライブラリ | 注記 |
|---|---|
@amazon-devices/react-native-kepler |
ヘッドレスJSコンテキストでは限られたモジュールのみを利用できます。上記の一覧を参照してください。ルートの@amazon-devices/react-native-keplerからはインポートしないでください。 |
@amazon-devices/headless-task-manager |
|
@amazon-devices/react-native-w3cmedia |
"@amazon-devices/react-native-w3cmedia/dist/headless"を使用して、対象のモジュールのみをインポートしてください。この「headless」エクスポートは、バージョン2.1.66以降でのみ提供されます。 |
@amazon-devices/react-native-mmkv |
|
@amazon-devices/react-native-async-storage/async-storage |
react-native-async-storageのドキュメントを参照してください。 |
@amazon-devices/kepler-media-account-login |
|
@amazon-devices/kepler-content-personalization |
|
@amazon-devices/kepler-epg-provider |
|
@amazon-devices/kepler-epg-sync-scheduler |
インポートのガイドライン
ヘッドレスランタイムでは、インポートできるものに厳密な制限があります。UIコンポーネントやサポートされていないライブラリをインポートすると、クラッシュが発生します。
以下の一覧に、安全にインポートできるユーティリティと、安全でないユーティリティの例を示します。
安全なインポート
✅ React Native標準の非UIユーティリティ:
import { Platform, Dimensions } from 'react-native';
✅ Vega固有のヘッドレスライブラリ:
import { HeadlessTaskManager } from '@amazon-devices/headless-task-manager';
import { ContentPersonalization } from '@amazon-devices/kepler-content-personalization';
✅ コアJavaScript API:
console.log('ヘッドレスサービスを開始しました');
fetch('https://api.example.com/data');
安全でないインポート
❌ UIコンポーネント(クラッシュが発生):
import { View, Text, Image } from 'react-native';
❌ UI関連のAPI(クラッシュが発生):
import { AppState, DeviceInfo } from 'react-native';
❌ ワイルドカードによるインポート(クラッシュが発生):
import * as RN from 'react-native';
ログに「Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'DeviceInfo' could not be found」のようなエラーが表示される場合は、ヘッドレスコンテキストで使用できないUIコンポーネントやUI関連のAPIがインポートされています。インポートを確認し、この記事のトラブルシューティングのセクションを参照してください。
サポートされていないモジュールを使用した場合
上記以外のモジュールやライブラリを使用すると、次の例のようなランタイムエラーが発生します。この例は、ヘッドレスJSコンテキストでは使用できないDeviceInfoモジュールに関するエラーを示しています。
E Volta:[KeplerScript-JavaScript] Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'DeviceInfo' could not be found.Verify that a module by this name is registered in the native binary., js engine: hermes.
このエラーは、問題のモジュールを直接インポートしていなくても発生することがあります。このエラーが発生するのは以下の場合です。
- 使用しているモジュールが、問題のあるモジュールをインポートしている。
- サポートされていないライブラリを使用している。
- モジュールのインポートが正しくない。
たとえば、ヘッドレスJSのコードを記述しているときに、ヘッドレスエクスポートではなく@amazon-devices/react-native-w3cmediaを直接インポートすると、このエラーが発生します。
import { VideoPlayer } from '@amazon-devices/react-native-w3cmedia/dist/headless'; // 正しい
import { VideoPlayer } from '@amazon-devices/react-native-w3cmedia'; // 間違い
@amazon-devices/react-native-w3cmediaのヘッドレスエクスポートには、ヘッドレスJSで安全に動作するモジュールのみが含まれています。このエクスポートを経由しないと、コードでは、@amazon-devices/react-native-keplerのDeviceInfoなど、サポートされていない機能に依存するUI関連のモジュールの読み込みが試みられ、エラーが発生することになります。
今後、サポートされていないモジュールをビルド時に検出するツールの追加を予定していますが、現時点では、VegaでヘッドレスJavaScript用に承認されているモジュールのみを使用するようにしてください。
ヘッドレスJSタスクおよびサービスのビルド
ヘッドレスJSタスクおよびヘッドレスJSサービスを登録するには、以下の手順を実行する必要があります。
手順1: アプリのマニフェスト(manifest.toml)でコンポーネントをアドバタイズする
// manifest.toml
# Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All rights reserved.
#
# 専有/機密情報。 使用にあたってはライセンス条項が適用されます。
#
schema-version = 1
[package]
title = "ヘッドレスJSタスクおよびサービスのデモ"
version = "1.0.0"
id = "com.yourcompany.headlessjsdemo"
[components]
[[components.interactive]]
id = "com.yourcompany.headlessjsdemo.main"
runtime-module = "/com.amazon.kepler.keplerscript.runtime.loader_2@IKeplerScript_2_0"
categories = ["com.amazon.category.main"]
# アプリにヘッドレスJSタスクがあることを示します。
[[components.task]]
id = "com.yourcompany.headlessjsdemo.task"
runtime-module = "/com.amazon.kepler.keplerscript.runtime.loader_2@IKeplerScript_2_0"
# アプリにヘッドレスJSサービスがあることを示します。
[[components.service]]
id = "com.yourcompany.headlessjsdemo.service"
runtime-module = "/com.amazon.kepler.keplerscript.runtime.loader_2@IKeplerScript_2_0"
launch-type = "singleton"
マニフェストファイルの違い
さまざまなヘッドレスJSタスク/サービスに応じて、manifest.tomlファイルには異なる設定が必要になります。以下に例を示します。
- EPG同期タスクには「
runtime-module = /com.amazon.kepler.headless.runtime.loader_2@IKeplerScript_2_0」を使用します。 - ヘッドレスJS再生には「
runtime-module = /com.amazon.kepler.keplerscript.runtime.loader_2@IKeplerScript_2_0」を使用します。
プロセス管理もユースケースによって異なります。
- ヘッドレスJS再生はUIと同じプロセスで実行されます。
- EPG同期タスクは別のプロセスで実行されます。
実装する各機能の固有のドキュメントを必ず確認してください。わずかな違いが大きい問題につながることがあるため、異なるヘッドレスJS機能間で設定をコピーしないでください。
手順2: エントリポイントを登録する
タスクとサービスのエントリポイント(タスクではdoTask関数、サービスではonStartServiceおよびonStopService関数を使用)を登録するには、task.jsとservice.jsという2つのファイルを個別に作成することをお勧めします。これらのファイルは、index.js(AppRegistry.registerComponentを使用してUIのエントリポイントを登録するファイル)と一緒に配置します。task.jsファイルとservice.jsファイルを使用して、複数のヘッドレスJSタスク/サービスのエントリポイントを登録できます。
// task.js - ヘッドレスJSタスクのエントリポイントを登録します。
import { HeadlessEntryPointRegistry } from "@amazon-devices/headless-task-manager";
// SampleHeadlessTask.tsにdoTaskが実装されています。
import { doTaskSampleTask } from "./src/SampleHeadlessTask";
HeadlessEntryPointRegistry.registerHeadlessEntryPoint2("com.yourcompany.headlessjsdemo.task::doTask",
() => doTaskSampleTask);
// service.js - ヘッドレスJSサービスのエントリポイントを登録します。
import {HeadlessEntryPointRegistry} from '@amazon-devices/headless-task-manager';
// SampleHeadlessService.tsにonStartSampleServiceとonStopSampleServieが実装されています。
import {onStartSampleService, onStopSampleService} from './src/SampleHeadlessService';
HeadlessEntryPointRegistry.registerHeadlessEntryPoint(
'com.yourcompany.headlessjsdemo.service::onStartService',
() => onStartSampleService,
);
HeadlessEntryPointRegistry.registerHeadlessEntryPoint(
'com.yourcompany.headlessjsdemo.service::onStopService',
() => onStopSampleService,
);
react-native build-vegaを使用してアプリをビルドする場合は、このプロセスによってヘッドレスJSバンドルが自動的に処理されます。次のファイルをプロジェクトのルートに配置してください。
- ヘッドレスタスクのtask.js
- ヘッドレスサービスのservice.js
ビルドシステムは、これらのファイルを検出して以下を作成します。
- タスクのtask.hermes.bundle
- サービスのservice.hermes.bundle
これらのバンドルが自動的にアプリパッケージ(VPKG)に含められます。
.jsという拡張子にする必要があります。これらの名前をtask.tsやservice.tsにすると、react-native build-vegaコマンドでファイルが検出されず、アプリのVPKGにtask.hermes.bundleやservice.hermes.bundleが取り込まれなくなります。その結果、ANR(アプリ応答なし)クラッシュやその他のランタイムエラーが発生する可能性があります。
// package.json
"scripts": {
.
.
"build:release": "react-native build-vega --build-type Release",
"build:debug": "react-native build-vega --build-type Debug",
"build:app": "npm-run-all build:release build:debug",
.
},
react-native build-vegaを使用しない場合は、次の手順を手動で実行する必要があります。
- エントリポイントファイル(
task.jsとservice.js)からHermesバイトコードバンドルを生成します。 - これらのバンドルを手動でアプリパッケージ(VPKG)に追加します。
ヘッドレスJSタスクおよびサービスのデバッグ
ログ
ヘッドレスJSタスク/サービスのコードをデバッグするには、コンソールログ(console.log)を使用し、その出力をデバイスログで確認できます。
デバイスまたはシミュレーターシェルから次のコマンドを実行します。
loggingctl log -f | grep -i "<your package name>\|KeplerScript-Native\|KeplerScript-JavaScript"
ログが切り捨てられないようにするには、デバイスまたはシミュレーターシェルから次のコマンドを実行します。
loggingctl config --set-rate all 60000
<デバイスを再起動>
loggingctl config --set-rate all 60000 // 再実行
再ビルドなしでのJSバンドルのクイック更新
ヘッドレスJSタスクおよびサービスで、アプリを再ビルドして再インストールしなくても、更新されたJSバンドルを取得できるようになりました。
ヘッドレスJSタスク/サービスでは、再起動せずに変更を反映できるホットリロードや高速リフレッシュはサポートされません。代わりに、ヘッドレスJSタスク/サービスを再起動して、更新されたJSバンドルを取り込む必要があります。
この機能を使用するには、次の手順に従います。
- アプリ(UIとヘッドレスJSコンポーネント)をデバッグモードでビルドします。注: UIコンポーネントと同様に、行単位のデバッグはリリースビルドでは機能しません。
- アプリをインストールします。
- プロジェクトルートからMetroサーバーを実行します(
npm start)。 - アプリとMetroで使用するように構成されているポート(通常は
8081)に、デバイス(target)から開発コンピューター(host)への逆方向のポートフォワーディングを設定します。この手順を実行しないと、アプリからMetroサーバーに接続することはできません。vega device start-port-forwarding --device <デバイス名> -p 8081 --forward false - アプリを起動します。これで、すべてのJSバンドル(UIとヘッドレスJSの両方)がMetroによって提供されるようになります。
行単位のデバッグ
ヘッドレスJSタスク/サービスは行単位でデバッグできますが、いくつかの制限があります。
- Vega StudioのDev Toolsでのみ機能します。
- Dev Toolsには最後に起動されたJSコンポーネントだけが表示されます。
たとえば、ヘッドレスJSメディア再生アプリでは次のようになります。
- UIとサービスの両方が同時に実行されます。
- サービスが最後に起動するため、Dev Toolsにはservice.bundleが表示されます。
- 代わりにUIをデバッグするには、次の手順を実行する必要があります。
vega device launch-app -a <ヘッドレスJSコンポーネント名>を使用して、最初にヘッドレスサービスを起動します。- 次にUIコンポーネントを起動します。
- これでDev Toolsにindex.bundleが表示されます。
行単位のデバッグを使用するには、次の手順に従います。
- アプリ(UIとヘッドレスJSコンポーネント)をデバッグモードでビルドします。注: UIコンポーネントと同様に、行単位のデバッグはリリースビルドでは機能しません。
- アプリをインストールします。
- プロジェクトルートからMetroサーバーを実行します(
npm start)。 - ポート8081(またはアプリとMetroに構成したポート)に、デバイス(
target)から開発コンピューター(host)への逆方向のポートフォワーディングを設定します。この手順を実行しないと、アプリからMetroサーバーに接続してDev Toolsとやり取りすることはできません。vega device start-port-forwarding --device <デバイス名> -p 8081 --forward false - デバッグするヘッドレスJSタスクまたはサービスを起動します。
- 手動で起動するために、
vega device launch-app -a <ヘッドレスJSコンポーネント名>というコマンドを実行します。 - UIコンポーネントを起動します。
- 手動で起動するために、
- Vega Studioでコマンドパレットを開き、「Vega: Launch Dev Tools」を選択します。[Sources] タブに移動し、[React Native] を選択します。
- デバッグしようとしている目的のバンドル(
index.bundle/service.bundle/task.bundle)が表示され、そのソースが読み込まれていることを確認します。注: Dev Toolsでは、ソースマップの読み込みの失敗に関するエラーが表示されますが、これは無視して構いません。 - ブレークポイントを設定するには、ターゲットのコードを検索し、ブレークポイントを追加する行番号をクリックします。ブレークポイントがヒットするのは、そのブレークポイントの設定後に実行されるコードに対してだけです。つまり、起動直後に実行されるコード(ヘッドレスJSタスクの
doTaskや、ヘッドレスJSサービスのonStartServiceなど)にブレークポイントを設定してもトリガーされません。このような場合のデバッグには、引き続きログを使用してください。 - Dev Toolsは自動的には更新されないため、アプリを起動し直す合間に、Dev Toolsインスタンスを閉じて再起動してください。

クラッシュレポート
ヘッドレスJSタスクまたはサービスから未処理のJSエラーが発生すると、アプリがクラッシュし、集約クラッシュレポート(ACR)が生成されます。この動作は現在、ヘッドレスJSタスク/サービスのリリースビルドにのみ適用されます。ヘッドレスJSタスク/サービスのデバッグビルドで未処理のJS例外を検出するには、引き続きデバイスログを使用してください。
ヘッドレスJSタスクおよびサービスに関する問題のトラブルシューティング
デバッグモードではヘッドレスJSタスク/サービスが動作するが、リリースモードでは起動しないかエラーが発生する
ログに次のようなエラーが表示される場合は、タスク/サービスバンドルが、ヘッドレスJSコンテキストでサポートされていないモジュールを初期化または使用しようとしています。
E Volta:[KeplerScript-JavaScript] Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'DeviceInfo' could not be found.Verify that a module by this name is registered in the native binary., js engine: hermes.
この状況に当てはまるかどうかを特定するには、以下の手順を実行します。
手順1: react-native-bundle-visualizerを使用して、ヘッドレスJSタスク/サービスバンドルの構成を確認する
たとえば、サポートされていないモジュールをタスクバンドルが@amazon-devices/react-native-keplerから誤って取り込んでいる場合は、task.bundleの構成を比較します。
npx react-native-bundle-visualizer --entry-file task.js
シナリオ1: 正しいインポート
// task.js
// 正しいインポート
import { ComponentType } from '@amazon-devices/react-native-kepler/Libraries/ComponentInstance/ComponentInstanceManager';
const componentInstance = {
name: "TestComponent",
type: ComponentType.TASK,
id: "test-123"
};
// 列挙値を文字列に変換してログに記録します。
console.log(`ヘッドレスタスクのテスト: コンポーネントタイプ:${ComponentType[componentInstance.type]}`);

シナリオ2: 間違ったインポート
// task.js
// 間違ったインポート
import { ComponentType } from '@amazon-devices/react-native-kepler';
const componentInstance = {
name: "TestComponent",
type: ComponentType.TASK,
id: "test-123"
};
// 列挙値を文字列に変換してログに記録します。
console.log(`ヘッドレスタスクのテスト: コンポーネントタイプ:${ComponentType[componentInstance.type]}`);

シナリオ2のtask.bundleの構成は、このバンドルに@amazon-devices/react-native-keplerから多数のモジュールが取り込まれ、ヘッドレスJSコンテキストでサポートされていないモジュールも含まれていることを示しています。サポートされていないモジュールがタスク/サービスバンドルに含まれていることを確認したら、手順2に進んで、それらのモジュールが取り込まれた原因を特定します。
手順2: Headless JS Bundle Validatorを使用してデバッグビルドのtask.bundle/service.bundleを検査する
Headless JS Bundle Validator
インポートに関する問題に対処するには、Headless JS Bundle Validatorを使用します。このツールは、ヘッドレスJSタスク/サービスのバンドルから、ヘッドレスJSコンテキストでサポートされていないモジュールを検出し、それらのモジュールの読み込み元をトレースします。
検証ツールは次の目的にも使用できます。
- トラブルシューティングのために依存関係グラフを生成する。
- 問題のあるインポートチェーンを開発者が追跡することを支援する。
- パッケージ内のバンドルの存在を検証する。
ダウンロード:headless-js-bundle-validator-1-0-1.zip(77.4MB)
手順3: Amazonの担当者に連絡する
サポートされていないモジュールを検出できずに行き詰まった場合は、Amazonが問題の診断をお手伝いします。Amazonの担当者にお問い合わせのうえ、サポートを依頼してください。
ヘッドレスJSタスクおよびサービスの現在の利用状況
ヘッドレスJSタスクは、次のFire TV統合で利用されています。
- 電子番組表
- アプリのインストール時またはアップデート時の処理のスケジュール: EPGの更新、アプリマニフェストのタスク
ヘッドレスJSサービスは、次のユースケースで利用されています。
Last updated: 2025年3月20日

