149 lines
5.9 KiB
Markdown
149 lines
5.9 KiB
Markdown
# Android ウィジェット機能 概要
|
||
|
||
## ウィジェット一覧(app.json 登録済み: 4種)
|
||
|
||
| 名前 | ラベル | 概要 |
|
||
|---|---|---|
|
||
| `JR_shikoku_train_info` | 列車遅延速報EX | GAS API から遅延データ取得→表示 |
|
||
| `JR_shikoku_train_strange` | 怪レい列車 | app.json に定義あるが専用レンダリング分岐なし |
|
||
| `JR_shikoku_info` | 運行情報 | app.json に定義あり。AsyncStorage の `widgetType/{id}` で `Info_Widget` に手動切替可能 |
|
||
| `JR_shikoku_apps_shortcut` | クイックアクセス | FeliCa IC カード残高表示 + タップでスキャン画面へディープリンク |
|
||
|
||
全ウィジェット共通: `updatePeriodMillis: 1800000`(30分)、`resizeMode: "horizontal|vertical"`
|
||
|
||
---
|
||
|
||
## ファイル構成
|
||
|
||
| ファイル | 役割 |
|
||
|---|---|
|
||
| `components/AndroidWidget/TraInfoEXWidget.tsx` | 遅延速報EXウィジェットUI + データ取得 |
|
||
| `components/AndroidWidget/InfoWidget.tsx` | 運行情報ウィジェットUI + データ取得 |
|
||
| `components/AndroidWidget/FelicaQuickAccessWidget.tsx` | クイックアクセスウィジェットUI + 残高データ取得 |
|
||
| `components/AndroidWidget/widget-task-handler.tsx` | ウィジェットイベントハンドラ(全ウィジェット共通) |
|
||
| `components/AndroidWidget/HelloWidgetPreviewScreen.tsx` | 死コード(`HelloWidget` が存在しない) |
|
||
| `components/Settings/WidgetSettings.tsx` | ウィジェット設定画面(ウィジェットIDごとに表示タイプ切替) |
|
||
| `index.ts` | `registerWidgetTaskHandler()` でハンドラ登録(Android のみ) |
|
||
| `app.json` | ウィジェットプラグイン設定 + intentFilters |
|
||
| `constants/storage.ts` | `FELICA_LAST_SNAPSHOT` キー定義 |
|
||
| `lib/rootNavigation.ts` | グローバルナビゲーション ref(`createNavigationContainerRef`) |
|
||
|
||
---
|
||
|
||
## ディープリンク設定
|
||
|
||
### intentFilters(app.json)
|
||
|
||
```json
|
||
[
|
||
{ "action": "VIEW", "data": [{"scheme": "jrshikoku"}],
|
||
"category": ["BROWSABLE", "DEFAULT"] },
|
||
{ "action": "VIEW",
|
||
"data": [{"scheme": "jrshikoku", "host": "open", "pathPrefix": "/felica"}],
|
||
"category": ["BROWSABLE", "DEFAULT"] }
|
||
]
|
||
```
|
||
|
||
### Linking config(Apps.tsx)
|
||
|
||
```typescript
|
||
const linking = {
|
||
prefixes: ["jrshikoku://"],
|
||
config: {
|
||
screens: {
|
||
positions: { screens: { Apps: "positions/apps" } },
|
||
topMenu: {
|
||
screens: {
|
||
menu: "topMenu/menu",
|
||
setting: {
|
||
screens: {
|
||
settingTopPage: "topMenu/setting",
|
||
FelicaHistoryPage: "topMenu/setting/FelicaHistoryPage",
|
||
},
|
||
},
|
||
},
|
||
},
|
||
information: "information",
|
||
},
|
||
},
|
||
};
|
||
```
|
||
|
||
---
|
||
|
||
## ウィジェットタップ → Felica スキャン画面 フロー
|
||
|
||
```
|
||
FelicaQuickAccessWidget タップ
|
||
→ clickAction="OPEN_URI", uri="jrshikoku://open/felica"
|
||
→ Android OS が intentFilter マッチでアプリ起動
|
||
→ App.tsx: Linking.getInitialURL() or addEventListener("url")
|
||
→ routeFromUrl(url): "open/felica" を検知
|
||
→ openFelicaPage(): rootNavigationRef.navigate("topMenu" > "setting" > "FelicaHistoryPage")
|
||
※ nav 未 ready なら 250ms × 最大8回 retry
|
||
→ FelicaHistoryPage で NFC スキャン画面表示
|
||
→ scan() 成功後:
|
||
- UI に結果表示
|
||
- AS.setItem(FELICA_LAST_SNAPSHOT, { balance, idm, systemCode, scannedAt })
|
||
- requestWidgetUpdate("JR_shikoku_apps_shortcut") でウィジェット即時更新
|
||
```
|
||
|
||
---
|
||
|
||
## widget-task-handler イベントディスパッチ
|
||
|
||
```
|
||
widgetAction:
|
||
WIDGET_ADDED / WIDGET_UPDATE / WIDGET_CLICK / WIDGET_RESIZED
|
||
→ widgetName === "JR_shikoku_apps_shortcut"
|
||
→ getFelicaQuickAccessData() → FelicaQuickAccessWidget 描画
|
||
→ それ以外
|
||
→ AS.getItem(`widgetType/${widgetId}`) でユーザー設定判定
|
||
- "Info_Widget" → getInfoString() → InfoWidget
|
||
- "JR_shikoku_train_info" → getDelayData() → TraInfoEXWidget (デフォルト)
|
||
|
||
WIDGET_DELETED
|
||
→ AS.removeItem(`widgetType/${widgetId}`)
|
||
```
|
||
|
||
---
|
||
|
||
## 残高スナップショット保存箇所
|
||
|
||
| ファイル | トリガー | ウィジェット更新 |
|
||
|---|---|---|
|
||
| `FelicaHistoryPage.tsx` (L159) | `handleScan()` 成功 | ✅ `requestWidgetUpdate` あり |
|
||
| `settings.tsx` (L63) | `testNFC()` 成功 | ⚠️ なし(次回定期更新まで反映されない) |
|
||
|
||
保存形式: `{ balance, idm, systemCode, scannedAt }` → AsyncStorage キー `felicaLastSnapshot`
|
||
|
||
---
|
||
|
||
## 通知タップ → ナビゲーション(useNotifications.tsx)
|
||
|
||
| 判定キー | アクション | ナビゲーション先 |
|
||
|---|---|---|
|
||
| `遅延速報ex`, `trainfoex`, `tra_info_ex` | `delay-ex` | topMenu/menu → ActionSheet `JRSTraInfo` |
|
||
| `怪レい列車bot`, `strange_train` | `strange-train` | positions/Apps |
|
||
| `運行情報`, `information` | `information` | information タブ |
|
||
|
||
チャンネルID / categoryIdentifier / data.category を優先判定、フォールバックで通知テキストの正規化マッチング。
|
||
|
||
---
|
||
|
||
## ネイティブモジュール(expo-felica-reader)
|
||
|
||
- エクスポート: `scan()` のみ
|
||
- 戻り値: `FelicaCardInfo { idm, balance, systemCode, history[] }`
|
||
- Android: `NfcF` (FeliCa) リーダーモード、サービスコード `0x090F` で残高+履歴読取
|
||
- `launchApp` 等のネイティブヘルパーは除去済み
|
||
|
||
---
|
||
|
||
## 既知の不整合・注意点
|
||
|
||
1. **`JR_shikoku_train_strange`**: app.json に定義済みだが widget-task-handler に専用描画分岐がない(`nameToWidget` にもマッピングなし)
|
||
2. **`HelloWidgetPreviewScreen.tsx`**: `HelloWidget` を import しているが該当ファイルが存在しない(死コード)
|
||
3. **`testNFC`(settings.tsx)**: スナップショット保存するが `requestWidgetUpdate` を呼ばないためウィジェット未同期
|
||
4. **ディープリンク**: `intentFilters` は app.json に追加済みだが**ネイティブビルド未実施**のため未検証
|