sdk-reference について
sdk-referenceは、Even Hub G2スマートグラスSDKを使うWebアプリ開発者向けのリファレンススキルです。ブリッジAPI、データ型、初期化手順、コンテナの検証規則を説明します。
主な機能
- 01ブリッジ初期化と呼び出し順の説明
- 02APIメソッドと型のリファレンス
- 03テキスト、リスト、画像コンテナの定義
- 04ページコンテナの重なり順検証の説明
活用シーン
- 01目的に合うSDKメソッドの確認
- 02グラスアプリ画面の作成と更新
- 03送信前のページコンテナデータ確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ even-realities/ everything-evenhub --skill sdk-referenceインストール後、Claude Code で/sdk-referenceを入力して読み込まれたか確認します。
詳細
Even Hub G2 スマートグラス SDK(@evenrealities/even_hub_sdk)の正式な SDK リファレンスです。$ARGUMENTS について質問された場合は、このドキュメントから関連する API、型、インターフェース、列挙型、またはメソッドを探して説明してください。引数が指定されていない場合は、利用可能なすべての API の概要を体系的に示してください。
アーキテクチャ
Web App (your code) <-> EvenAppBridge (SDK) <-> Even App (host) <-> G2 Glasses
アプリは、Even コンパニオンアプリ内でホストされる Flutter WebView で実行される、標準的な HTML + TypeScript のウェブページです。特別なフレームワークは必要ありません。Vite + TypeScript だけで問題なく動作します。
インストール
npm install @evenrealities/even_hub_sdk
現在のバージョン:0.0.12
初期化
waitForEvenAppBridge() — 非同期、推奨
ネイティブブリッジの準備が整うと解決されます。常に同期シングルトンよりこちらを優先してください。
import { waitForEvenAppBridge } from '@evenrealities/even_hub_sdk'
const bridge = await waitForEvenAppBridge()
EvenAppBridge.getInstance() — 同期シングルトン
ブリッジがすでに初期化された後にのみ呼び出してください(例:waitForEvenAppBridge() の解決後に実行されるコールバック内)。
import { EvenAppBridge } from '@evenrealities/even_hub_sdk'
const bridge = EvenAppBridge.getInstance()
必須の呼び出し順序
waitForEvenAppBridge()— ブリッジを待ちますbridge.createStartUpPageContainer(container)— 起動時に必ず1回だけ呼び出します(メガネのマイク音声と IMU に必要です)- その他すべて:
audioControl、imuControl、rebuildPageContainer、イベントリスナー、位置情報、写真ピッカー/カメラなど
createStartUpPageContainer が最初に成功していない場合、audioControl(true, AudioInputSource.Glasses) と imuControl は失敗します。audioControl(true, AudioInputSource.Phone)、位置情報 API、pickImageFromAlbum、captureImageFromCamera は、スマートグラスではなくスマートフォン経由で処理されるため、起動ページは必要ありません。
メソッドの完全なリファレンス
| メソッド | 戻り値 | 説明 |
|---|---|---|
bridge.getUserInfo() | Promise<UserInfo> | サインイン中のユーザーの uid、名前、アバター URL、国を取得します |
bridge.getDeviceInfo() | Promise<DeviceInfo | null> | 接続されているメガネのモデル、シリアル番号、ステータスを取得します。デバイスがない場合は null を返します。 |
bridge.setLocalStorage(key, value) | Promise<boolean> | キーと値の文字列ペアをコンパニオンアプリのストレージに保存します |
bridge.getLocalStorage(key) | Promise<string> | キーを指定して保存済みの文字列を読み込みます。キーが存在しない場合は空文字列を返します |
bridge.createStartUpPageContainer(container) | Promise<StartUpPageCreateResult> | すべての UI コンテナーを定義する、起動時に一度だけ呼び出すメソッドです。0=成功、1=無効、2=サイズ超過、3=メモリ不足 |
bridge.rebuildPageContainer(container) | Promise<boolean> | すべてのコンテナーを破棄して、完全に再描画します |
bridge.textContainerUpgrade(container) | Promise<boolean> | 全体を再描画せずにテキストをその場で更新します(1 回の呼び出しにつき最大 2000 文字) |
bridge.updateImageRawData(data) | Promise<ImageRawDataUpdateResult> | 画像コンテナーを埋めるための生ピクセルデータを送信します。SDK 内部で LZ4 圧縮されます(0.0.12 以降)。これまでどおり生ピクセルデータを渡してください。呼び出しは順番に行い、次の呼び出しの前に各処理を await してください。 |
bridge.shutDownPageContainer(exitMode?) | Promise<boolean> | アプリを閉じます。exitMode 0=直ちに終了、1=確認ダイアログを表示 |
bridge.onLaunchSource(cb) | () => void | 起動元イベントを購読します。'appMenu' または 'glassesMenu' が必ず一度だけ発生します。購読解除関数を返します。 |
bridge.onDeviceStatusChanged(cb) | () => void | デバイスのステータス更新(接続タイプ、バッテリー、装着状態、充電状態)を購読します。購読解除関数を返します。 |
bridge.onEvenHubEvent(cb) | () => void | すべてのハブイベント(listEvent、textEvent、sysEvent、audioEvent)を購読します。購読解除関数を返します。 |
bridge.audioControl(isOpen, source?) | Promise<boolean> | マイクを開く(true)か閉じる(false)かを指定します。source は AudioInputSource の値で、Glasses(デフォルト。G2 の 4 マイクアレイ)または Phone(スマートフォンのマイク)です。音声は source フィールドが設定された状態で、PCM 形式の audioEvent として配信されます。 |
bridge.imuControl(isOpen, reportFrq?) | Promise<boolean> | IMU センサーを有効または無効にします。reportFrq は ImuReportPace の値(P100~P1000)です。 |
bridge.getAppLocation(options?) | Promise<AppLocation | null> | 位置情報を一度だけ読み込みます。options では accuracy、timeoutMs を指定できます。時間内に位置情報を取得できない場合、権限が拒否された場合、または座標が無効な場合は null を返します。 |
bridge.startAppLocationUpdates(options?) | Promise<boolean> | 位置情報の継続的な更新を開始します。options では accuracy、intervalMs、distanceFilter を指定できます。onAppLocationChanged を購読すると更新を受け取れます。 |
bridge.stopAppLocationUpdates() | Promise<boolean> | startAppLocationUpdates で開始した位置情報の継続的な更新を停止します。 |
bridge.onAppLocationChanged(cb) | () => void | 位置情報の継続的な更新を購読します。コールバックには AppLocation が渡されます。購読解除関数を返します。 |
bridge.pickImageFromAlbum() | Promise<AppImageAsset | null> | スマートフォンの写真アルバムを開き、画像を 1 枚選択します。ユーザーがキャンセルした場合、または album 権限を拒否した場合は null を返します。 |
bridge.captureImageFromCamera() | Promise<AppImageAsset | null> | スマートフォンのカメラを開き、画像を 1 枚撮影します。ユーザーがキャンセルした場合、または camera 権限を拒否した場合は null を返します。G2 にはメガネに搭載されたカメラはありません。 |
bridge.callEvenApp(method, params?) | Promise<any> | ネイティブブリッジメソッドを直接呼び出す低レベルのメソッドです。より高レベルのメソッドが利用できない場合に使用します。 |
TypeScript インターフェース
TextContainerProperty
テキスト表示コンテナーを定義します。
SDK のコンストラクターでは、すべてのフィールドが省略可能です(Partial<T> を受け付けます)。レイアウトに必要なフィールドを設定してください。
class TextContainerProperty {
xPosition?: number // 0–576, horizontal offset from left edge
yPosition?: number // 0–288, vertical offset from top edge
width?: number // 0–576, container width
height?: number // 0–288, container height
borderWidth?: number // 0–5, border thickness in pixels
borderColor?: number // 0–15, greyscale colour index
borderRadius?: number // 0–10, corner radius
paddingLength?: number // 0–32, inner padding in pixels
containerID?: number // unique integer ID for this container
containerName?: string // max 16 characters
isEventCapture?: number // 0 or 1; exactly one container per page must be 1
zOrderIndex?: number // stacking order, larger = front; all-or-nothing per page (0.0.12+, see Z-Order Rules)
content?: string // initial text content, max 1000 characters
}
ListContainerProperty
スクロール可能なリストコンテナーを定義します。
class ListContainerProperty {
xPosition?: number // 0–576
yPosition?: number // 0–288
width?: number // 0–576
height?: number // 0–288
borderWidth?: number // 0–5
borderColor?: number // 0–15
borderRadius?: number // 0–10
paddingLength?: number // 0–32
containerID?: number
containerName?: string // max 16 characters
isEventCapture?: number // 0 or 1
zOrderIndex?: number // stacking order, larger = front; all-or-nothing per page (0.0.12+, see Z-Order Rules)
itemContainer?: ListItemContainerProperty
}
ListItemContainerProperty
リストコンテナー内の項目を定義します。
class ListItemContainerProperty {
itemCount?: number // 1–20, number of items
itemWidth?: number // item width; 0 = auto (fills container)
isItemSelectBorderEn?: number // 0 or 1; 1 = show selection border around highlighted item
itemName?: string[] // array of item label strings; max 20 items, max 64 chars each
}
ImageContainerProperty
プレースホルダーの画像コンテナーを定義します。作成後、updateImageRawData を使ってデータを設定する必要があります。画像コンテナーは isEventCapture をサポートしていません。画像と組み合わせて使う場合は、イベントキャプチャレイヤーとしてテキストコンテナーを使用してください。
class ImageContainerProperty {
xPosition?: number // 0–576
yPosition?: number // 0–288
width?: number // 20–288
height?: number // 20–144
containerID?: number
containerName?: string // max 16 characters
zOrderIndex?: number // stacking order, larger = front; all-or-nothing per page (0.0.12+, see Z-Order Rules)
}
TextContainerUpgrade
bridge.textContainerUpgrade() のペイロードです。
class TextContainerUpgrade {
containerID?: number
containerName?: string // max 16 characters
contentOffset?: number // character offset to begin writing
contentLength?: number // number of characters to replace
content?: string // replacement text, max 2000 characters total
}
ImageRawDataUpdate
bridge.updateImageRawData() のペイロードです。
class ImageRawDataUpdate {
containerID?: number
containerName?: string
imageData?: number[] | string | Uint8Array | ArrayBuffer // raw pixel data in 4-bit greyscale
}
0.0.12 以降、SDK は転送サイズと更新レイテンシーを削減するため、転送前に画像の生データを内部で LZ4 圧縮します。これまでと同じように生のピクセルデータを渡してください。設定が必要な圧縮フラグはありません。
CreateStartUpPageContainer
bridge.createStartUpPageContainer() のパラメーター型です。
class CreateStartUpPageContainer {
containerTotalNum?: number // 1–12, total number of containers
widgetId?: number // auto-assigned; omit to let SDK assign
listObject?: ListContainerProperty[] // list containers
textObject?: TextContainerProperty[] // text containers, max 8
imageObject?: ImageContainerProperty[] // image containers, max 4
}
RebuildPageContainer
bridge.rebuildPageContainer() のパラメーター型です。CreateStartUpPageContainer と同じ構造ですが、widgetId はありません。
class RebuildPageContainer {
containerTotalNum?: number // 1–12, total number of containers
listObject?: ListContainerProperty[] // list containers
textObject?: TextContainerProperty[] // text containers, max 8
imageObject?: ImageContainerProperty[] // image containers, max 4
}
Zオーダールール(0.0.12 以降)
zOrderIndex は、ページ上のすべてのコンテナーの前後関係を制御します。SDK はペイロードがネイティブブリッジに到達する前に、以下のルールを検証します。
- ページ単位で全て設定するか、全て省略する — ページ上のすべてのリスト/テキスト/画像コンテナーで
zOrderIndexを設定するか、どのコンテナーにも設定しないでください。すべて省略した場合は、0.0.12 より前の動作が維持されます(宣言順序によって重なり順が決まります)。 - ページ内で一意にする — 同じページ上の複数のコンテナーに同じ値を指定することはできません。同値の場合の優先順位はありません。
- 値が大きいほど手前に表示されます。
ルールに違反すると、SDK は EvenHubPageContainerValidationErrorCode エラーをログに記録し、ネイティブ側の処理を呼び出しません。createStartUpPageContainer は StartUpPageCreateResult.invalid を返し、rebuildPageContainer は false を返します。
enum EvenHubPageContainerValidationErrorCode {
MissingZOrderIndex = 'MISSING_Z_ORDER_INDEX', // some containers set zOrderIndex, others omit it
InvalidZOrderIndex = 'INVALID_Z_ORDER_INDEX', // value is not a valid number
DuplicateZOrderIndex = 'DUPLICATE_Z_ORDER_INDEX' // two containers share a value
}
// Run the same validation yourself before sending a page payload:
function validateEvenHubPageContainerZOrder(container: EvenHubPageContainerLike): EvenHubPageContainerValidationResult
// Human-readable message for an invalid result:
function formatEvenHubPageContainerValidationError(result): string
UserInfo
interface UserInfo {
uid: number // numeric user ID
name: string // display name
avatar: string // URL to avatar image
country: string // ISO country code or name
}
DeviceInfo
interface DeviceInfo {
readonly model: DeviceModel // glasses model identifier
readonly sn: string // serial number
status: DeviceStatus // current connection status object
}
DeviceStatus
interface DeviceStatus {
sn: string
connectType: DeviceConnectType
isWearing?: boolean // true if glasses are being worn
batteryLevel?: number // 0–100, battery percentage
isCharging?: boolean // true if glasses are charging
isInCase?: boolean // true if glasses are in the charging case
// Instance helpers
isNone(): boolean
isConnected(): boolean
isConnecting(): boolean
isDisconnected(): boolean
isConnectionFailed(): boolean
// Static factory methods
static fromJson(json: Record<string, any>): DeviceStatus
static createDefault(sn?: string): DeviceStatus
}
AppLocation
getAppLocation から返され、onAppLocationChanged を通じて通知される位置情報ペイロードです。
interface AppLocation {
latitude: number // degrees
longitude: number // degrees
accuracy?: number // horizontal accuracy in meters
altitude?: number // meters above sea level
speed?: number // meters per second
heading?: number // degrees from true north
timestamp?: number // Unix milliseconds
}
AppLocationOptions
getAppLocation と startAppLocationUpdates で受け付けられるオプションオブジェクトです。すべてのフィールドは省略可能です。
interface AppLocationOptions {
accuracy?: AppLocationAccuracy // Low | Medium | High
timeoutMs?: number // one-shot only
intervalMs?: number // continuous only
distanceFilter?: number // continuous only; meters — host skips smaller pushes
}
AppImageAsset
pickImageFromAlbum と captureImageFromCamera から返される画像ペイロードです。
interface AppImageAsset {
path: string // host-side path; opaque to the WebView
name: string // original filename
mimeType: string // e.g. "image/jpeg", "image/png"
size: number // bytes
base64: string // inline data, ready for <img src="data:..."> or further processing
}
イベントモデル
EvenHubEvent
bridge.onEvenHubEvent(cb) のコールバック型です。
interface EvenHubEvent {
listEvent?: List_ItemEvent
textEvent?: Text_ItemEvent
sysEvent?: Sys_ItemEvent
audioEvent?: AudioEventPayload
jsonData?: Record<string, any> // raw payload passthrough
}
AudioEventPayload
event.audioEvent のマイク音声ペイロードです。source はバッファの取得元となったマイクを示します。実行時に audioControl(true, ...) で音源を切り替える場合に役立ちます。
interface AudioEventPayload {
source: AudioInputSource // Glasses | Phone
audioPcm: Uint8Array // PCM 16 kHz, signed 16-bit little-endian, mono
}
Text_ItemEvent
テキストコンテナーがユーザー操作を受け取ると発生します。
interface Text_ItemEvent {
containerID?: number
containerName?: string
eventType?: OsEventTypeList
}
List_ItemEvent
リスト項目が選択またはスクロールされると発生します。
interface List_ItemEvent {
containerID?: number
containerName?: string
currentSelectItemName?: string // label of the currently selected item
currentSelectItemIndex?: number // 0-based index of the selected item
eventType?: OsEventTypeList
}
Sys_ItemEvent
IMU データやライフサイクルシグナルなどのシステムレベルのイベントです。
interface Sys_ItemEvent {
eventType?: OsEventTypeList
eventSource?: EventSourceType
imuData?: IMU_Report_Data
systemExitReasonCode?: number
}
IMU_Report_Data
グラスの IMU センサーから取得した、加速度計/ジャイロスコープの生データです。
interface IMU_Report_Data {
x?: number // X-axis value
y?: number // Y-axis value
z?: number // Z-axis value
}
LaunchSource
type LaunchSource = 'appMenu' | 'glassesMenu'
列挙型
enum OsEventTypeList {
CLICK_EVENT = 0,
SCROLL_TOP_EVENT = 1,
SCROLL_BOTTOM_EVENT = 2,
DOUBLE_CLICK_EVENT = 3,
FOREGROUND_ENTER_EVENT = 4,
FOREGROUND_EXIT_EVENT = 5,
ABNORMAL_EXIT_EVENT = 6,
SYSTEM_EXIT_EVENT = 7,
IMU_DATA_REPORT = 8
}
enum DeviceConnectType {
None = 'none',
Connecting = 'connecting',
Connected = 'connected',
Disconnected = 'disconnected',
ConnectionFailed = 'connectionFailed'
}
enum StartUpPageCreateResult {
success = 0,
invalid = 1,
oversize = 2,
outOfMemory = 3
}
enum ImageRawDataUpdateResult {
success = "success",
imageException = "imageException",
imageSizeInvalid = "imageSizeInvalid",
imageToGray4Failed = "imageToGray4Failed",
sendFailed = "sendFailed"
}
enum EvenAppMethod {
GetUserInfo = 'getUserInfo',
GetGlassesInfo = 'getGlassesInfo',
SetLocalStorage = 'setLocalStorage',
GetLocalStorage = 'getLocalStorage',
GetAppLocation = 'getAppLocation',
StartAppLocationUpdates = 'startAppLocationUpdates',
StopAppLocationUpdates = 'stopAppLocationUpdates',
PickImageFromAlbum = 'pickImageFromAlbum',
CaptureImageFromCamera = 'captureImageFromCamera',
CreateStartUpPageContainer = 'createStartUpPageContainer',
RebuildPageContainer = 'rebuildPageContainer',
UpdateImageRawData = 'updateImageRawData',
TextContainerUpgrade = 'textContainerUpgrade',
AudioControl = 'audioControl',
ImuControl = 'imuControl',
ShutDownPageContainer = 'shutDownPageContainer'
}
enum AudioInputSource {
Glasses = 'glasses', // G2 four-mic array (default; requires createStartUpPageContainer first)
Phone = 'phone' // phone microphone (no startup-page requirement)
}
enum AppLocationAccuracy {
Low = 'low', // city-level — cheapest, kindest to battery
Medium = 'medium', // block-level — balanced default
High = 'high' // best available fix — most battery
}
// ImuReportPace — reporting frequency for IMU sensor data
// Value = milliseconds between reports (P100 = 100 ms = 10 Hz, P1000 = 1000 ms = 1 Hz)
enum ImuReportPace {
P100 = 100,
P200 = 200,
P300 = 300,
P400 = 400,
P500 = 500,
P600 = 600,
P700 = 700,
P800 = 800,
P900 = 900,
P1000 = 1000
}
enum EventSourceType {
TOUCH_EVENT_FORM_DUMMY_NULL = 0,
TOUCH_EVENT_FROM_GLASSES_R = 1,
TOUCH_EVENT_FROM_RING = 2,
TOUCH_EVENT_FROM_GLASSES_L = 3
}
enum DeviceModel {
G1 = 'g1',
G2 = 'g2',
Ring1 = 'ring1'
}
結果コード
createStartUpPageContainer / StartUpPageCreateResult
| コード | 名前 | 意味 |
|---|---|---|
| 0 | success | コンテナーが正常に作成されました |
| 1 | invalid | コンテナーの設定が無効です |
| 2 | oversize | コンテナーの合計サイズがディスプレイの上限を超えています |
| 3 | outOfMemory | デバイスのメモリが不足しています |
updateImageRawData / ImageRawDataUpdateResult
| 名前 | 意味 |
|---|---|
| success | 画像データが受け付けられ、描画されました |
| imageException | 一般的な画像処理エラーです |
| imageSizeInvalid | 画像の寸法がコンテナーの寸法と一致しません |
| imageToGray4Failed | 画像を4ビットグレースケールに変換できませんでした |
| sendFailed | グラスへのデータ送信時にトランスポートエラーが発生しました |
重要なルール
createStartUpPageContainerは一度だけ実行できます — 起動時に必ず一度だけ呼び出してください。再度呼び出しても機能しません。それ以降の全体再描画にはrebuildPageContainerを使用してください。isEventCapture: 1を設定するコンテナは必ず1つだけにしてください — これにより、ユーザー入力を受け取るコンテナが指定されます。0個または複数設定すると、動作は未定義になります。zOrderIndexはページ単位で設定するか、まったく設定しないかのどちらかです(0.0.12+) — いずれかのコンテナに設定する場合、そのページのすべてのリスト/テキスト/画像コンテナに、重複しない値を設定する必要があります。値が大きいものほど手前に描画されます。違反すると SDK 側の検証に失敗します。createStartUpPageContainerはinvalidを返し、rebuildPageContainerはfalseを返します。- コンテナ数の上限 —
containerTotalNumは 1~12 にしてください。textObject配列の最大数は8項目、imageObject配列の最大数は4項目です。 - 画像の送信は直列に行ってください —
updateImageRawDataの呼び出しはキューに入れ、1件ずつ完了を待つ必要があります。同時呼び出しはサポートされておらず、エラーが発生します。 - 画像コンテナはプレースホルダーです —
createStartUpPageContainerが成功した後も、updateImageRawDataでデータを設定するまでは画像コンテナは空です。 - メガネのマイク用の
audioControlとimuControlを使用するには、起動が成功している必要があります —createStartUpPageContainerがStartUpPageCreateResult.successを返す前にaudioControl(true, AudioInputSource.Glasses)やimuControlを呼び出すと失敗します。audioControl(true, AudioInputSource.Phone)、位置情報 API、pickImageFromAlbum、captureImageFromCameraはスマートフォン経由で動作するため、起動画面を必要としません。 - 終了時には必ずイベントリスナーの登録を解除してください —
onEvenHubEvent、onDeviceStatusChanged、onLaunchSourceはいずれも登録解除関数を返します。コンポーネントまたはページが破棄されるときに呼び出してください。 onLaunchSourceは一度しか発火しません — イベントを取り逃さないよう、早い段階で(waitForEvenAppBridgeの前、または直後に)リスナーを登録してください。
キャンバスの仕様
| プロパティ | 値 |
|---|---|
| 解像度 | 576 × 288 px |
| 色深度 | 4ビットグレースケール(16階調、0 = 黒、15 = 白) |
| 座標の原点 | 左上の (0, 0) |
| X 軸 | 右方向に増加 |
| Y 軸 | 下方向に増加 |
ホストのプッシュ形式(シミュレーター/テスト)
コンパニオンアプリ(およびシミュレーター)は、window.postMessage を介して WebView にイベントをプッシュします。通常、これらを直接処理する必要はありません。SDK が内部で処理します。ただし、テストやカスタムシミュレーターの作成時には、これらの形式が役立ちます。
// Format 1 — named event type with jsonData wrapper
{ type: 'listen_even_app_data', method: 'evenHubEvent', data: { type: 'listEvent', jsonData: { /* event payload */ } } }
// Format 2 — snake_case event type with data wrapper
{ type: 'listen_even_app_data', method: 'evenHubEvent', data: { type: 'list_event', data: { /* event payload */ } } }
// Format 3 — array format [eventType, payload]
{ type: 'listen_even_app_data', method: 'evenHubEvent', data: ['list_event', { /* event payload */ }] }
// Audio event — audioPcm is an array of PCM sample integers; source identifies the mic
{ type: 'listen_even_app_data', method: 'evenHubEvent', data: { type: 'audioEvent', jsonData: { source: 'glasses', audioPcm: [/* numbers */] } } }
// Device status changed
{ type: 'listen_even_app_data', method: 'deviceStatusChanged', data: { sn: 'ABC123', connectType: 'connected', isWearing: true, batteryLevel: 80, isCharging: false } }
// Launch source (fires once on app open)
{ method: 'evenAppLaunchSource', data: { launchSource: 'appMenu' } }
// App location changed (pushed continuously after startAppLocationUpdates)
{ method: 'appLocationChanged', data: { latitude: 37.7749, longitude: -122.4194, accuracy: 5, timestamp: 1750000000000 } }
タスク
SDK のリファレンスを調べてください:$ARGUMENTS