afさんのAIラボ|制作中のClaude Codeとのやりとり
AF-SensorMonitor 1.0.0 企画・仕様検討
Android向けのセンサー計器盤アプリ「AF-SensorMonitor」を、Claude Codeと作ったときの会話記録です。仕様のレビューの依頼から、実装、4台の実機での確認、開発を一旦終えるまでを収録しています。
最初の長い依頼文は、外部チャットで企画と要件定義を行い、製造のために生成したプロンプトです。進め方は私とAIコーディングで紹介しています。端末のシリアル番号やローカルのパスなど、公開に不要な情報は削除しています。
👤 筆者 2026-09-25 18:06
🤖 Claude Code 2026-09-25 18:10
要件を確認し、規約資料集(README・適用範囲・構成管理・Git運用・Android規約・新規プロジェクト作成手順・テンプレート)を読みました。開発環境には Android Studio、SDK(platform 37 / build-tools 36)、JDK があります。指示どおり、コードとプロジェクトはまだ作っていません。端末ごとのセンサー構成も調べていません。
AF-SensorMonitor 1.0.0 仕様レビュー
1. 実現性
十分に作れます。 SensorManager.getSensorList(Sensor.TYPE_ALL) で、アプリから見えるセンサーを動的に全部列挙できます。メーカー独自のセンサー(TYPE 65536以上)や未知のTYPEも含まれます。
- Sensor APIだけで作れます。カメラ・位置情報・ストレージの権限は要りません。
- メーカー判定は必要ありません。名前・単位の対応表は、AOSP公開APIの標準TYPE定数(
TYPE_ACCELEROMETERなど)にだけ持たせます。これは特定機種向けの実装にあたりません。 - 表に載っていないTYPEは「汎用表示」にします(値の個数も単位も分からない前提)。何も除外しません。
2. Android上での実装方針
| 項目 | 方針 |
|---|---|
| 言語・UI | Kotlin + Jetpack Compose、Activityは1つ、画面は3つ。Unityは使いません。オーバースペックで、Sensorの細かいメタ情報も扱いにくいためです |
| minSdk / target | minSdk 26(Android 8.0)を提案します。getId・isDynamicSensor などに必要です。target・compileSdkは導入済みの最新SDKに合わせます |
| 購読 | 画面が前面にある間だけ購読します(onStartで登録、onStopで解除)。Android 9以降、バックグラウンドのアプリには連続型センサーの値が届かないため、この形が自然です |
| 取得頻度 | 約50Hz(20ms)を上限にします。Android 12以降、200Hzを超える取得には権限が必要ですが、今回は不要です |
| 描画 | センサー値は各センサーのリングバッファへ書くだけにし、UIが読みに行きます。数値の文字は約12Hz、インジケーターとグラフは画面のリフレッシュレートで更新します。文字はこれより速く変えても読めません |
| 画面ON維持 | アプリが前面にある間は KEEP_SCREEN_ON にします。振っている間に画面が消えるのを防ぐためです |
3. UI案
メイン画面(縦持ち・等幅数字・1行に1センサー)
AF-SensorMonitor SM-S9xx ● LIVE ⚙
● ACCEL +0.12 -0.20 +9.81 m/s²
● GYRO +0.00 +0.01 -0.10 rad/s
○ MAG +21.3 -12.8 -40.2 μT
○ LIGHT 428 lx
○ PROX FAR
– PRESS 1002.4 hPa
● GRAV +0.10 -0.19 +9.80 m/s²
● LINACC +0.02 -0.01 +0.03 m/s²
● ROTVEC 182° -3° 1°
◇ SIGMOT 待機
🔒 STEPCNT 未許可
○ VENDOR… 0.00 12.0 3.0 …+2
- 行の構成:[インジケーター][短い名前(固定幅)][値(右寄せ・桁固定)][単位(淡色・小さめ)]
- 値は桁数と符号の位置を固定し、数字が変わっても行幅が揺れないようにします。
- 値が4個以上ある場合:
- uncalibrated系は先頭の3値を表示します。
- 回転ベクトル(四元数)は方位・ピッチ・ロールの角度に換算して表示します。
- 未知のセンサーは先頭の3値の後ろに
…+Nと付けます。全値は詳細画面に出します。 - 短い名前が重複する場合は
#2を付けます。Wake-up版は小さな印で区別します。 - 状態記号は最小限にします:
●反応中、○静止、–まだ値が来ていない、◇トリガー待ち、🔒権限が必要、×購読できない。 - ヘッダーの
● LIVEをタップすると、メイン画面全体を一時停止(HOLD)できる案です。スクリーンショット撮影に便利で、実装も小さく済みます。
詳細画面
上から順に、次を表示します。
- 正式名称と現在値(全チャンネル)
- 20秒のグラフと PAUSE ボタン
- メタ情報の表
表示設定画面
- 上部:「全表示」「初期順序」「Export」
- その下:☰ハンドル付きの一覧にON/OFFトグルを並べます。
4. 取得できる情報と制約(端末に依存する注意点を含む)
取得できるメタ情報:Name、Vendor、Version、Type、StringType、Resolution、MaximumRange、Power、MinDelay / MaxDelay、ReportingMode、isWakeUpSensor、isDynamicSensor、Id、FIFO予約数 / 最大数、isAdditionalInfoSupported、HighestDirectReportRateLevel。精度(accuracy)の状態変化も受け取れます。
制約・端末依存の注意点
- ReportingModeで動きが違います。
- continuous:常に値が届きます。
- on-change:値が変わるまで届かないので、起動直後は値が空(
–)になります。 - one-shot(例:Significant Motion):registerListenerでは受け取れず、requestTriggerSensorで待ち受け、発火したら再度待ち受ける必要があります。 - special:ステップ検出などです。 - 近接センサーは二値(0 / 最大値)しか返さない端末が多いです。値が最大値未満なら NEAR、それ以外は FAR と表示します。
- 権限が必要なセンサーがあります。
- 歩数計・ステップ検出:
ACTIVITY_RECOGNITIONが必要です。 - 心拍などの身体センサー:BODY_SENSORSが必要です。新しいAndroidでは健康系の権限に置き換わっています。 - 権限がなくても一覧には出ますが、値は届きません。 - 同じTYPEのセンサーが複数あることがあります(Wake-up版と通常版、前面と背面など)。どれも除外せず並べます。
- Vendorセンサーは次のような動きをする可能性があります。いずれも行単位で状態を表示し、アプリ全体は止めません。 - 登録に失敗する - 条件がそろわないと値を出さない - 値の個数が一定でない
- SensorのIdは常に安定しているとは限りません。設定を保存するキーは、type・stringType・name・vendor・wakeUp・同一キー内の出現順から作ります。
- 向き:回転を試している最中に画面が回るのは致命的です。スマホは縦に固定します。ただし新しいAndroidをtargetにすると、大画面端末ではアプリ側の向き固定が無視されます。タブレットは横向きでも崩れず、状態も失わないように作ります(構成変更で再生成しない)。
- 外付けのHIDセンサーなど、動的センサーが後から現れた場合は、
DynamicSensorCallbackで一覧に追加します。 - OSの外部に公開されていないHAL内部のセンサーは見えません。「全センサー」は「アプリから見えるすべて」という意味になります。
5. 仕様上の問題点と改善提案
| # | 問題 | 提案 |
|---|---|---|
| 1 | 例示の GRAVITY 9.81 のような1値表示と、3軸を同じ行に並べる方針が混在している |
ベクトル量はすべて3軸で表示する。1行30文字程度に収まります |
| 2 | ROTATION 182° は元データが四元数 |
角度(方位・ピッチ・ロール)に換算して表示する |
| 3 | 刺激を与えてから詳細を開くと、その瞬間を見逃す | 表示中の全センサーについて、20秒分の履歴を常時保持する。タップした時点で直前の反応がグラフに残っています(これが一番の改善点です) |
| 4 | 画面の自動回転と自動消灯 | 縦固定と画面ON維持(上記) |
| 5 | 磁気センサーなどの精度変化が見えない | 詳細画面に精度(UNRELIABLE〜HIGH)を表示する |
| 6 | 値が一度も来ないセンサーが「壊れて見える」 | –(未受信)と ×(購読できない)を分け、詳細画面に受信したイベント数を出す |
| 7 | 文字サイズの設定次第で密度の基準が崩れる | sp単位でOSの設定に従い、あふれた分はスクロールにする(アクセシビリティを優先) |
6. 活動インジケーターの判定方法(提案)
固定の閾値ではなく、センサーごとに「静かなときの揺らぎ」を自動で学習し、それを大きく超えた変化を「反応」とする方式にします。
- 1サンプルごとの変化量を求めます:前回との差をチャンネルごとに出し、ベクトルの大きさにまとめます。角度は0°と360°の境目をまたぐ差を正しく扱い、四元数は同じ向きを表す符号反転を正しく扱います。
- 変化量の典型値を非対称なEMA(指数移動平均)で推定します。 - 値が小さくなる方向へは速く追従します(時定数 約0.5秒)。 - 大きくなる方向へはゆっくり追従します(時定数 約10秒)。 - こうすると静止時の揺らぎには素早く合い、振り続けても「反応中」がすぐには消えません。
- 反応スコア = 変化量 ÷ max(揺らぎ推定, 下限値)。 - 下限値は Resolution の数倍と、MaximumRange のごく小さな割合を使います。 - 標準TYPEは種類別に下限値を調整できます(照度は対数スケールで評価するなど)。
- 表示は すぐ点灯して、ゆっくり消える ようにします:スコアが閾値を超えたら即座に明るくし、約1秒かけて減衰させます。明るさは3段階程度にして、強く振るほど明るくします。
- 例外の扱い: - on-change型、トリガー型、ステップ検出:イベントが来た時点で「反応」とします。 - 起動直後の約1秒は学習だけ行い、点灯させません。
- 判定ロジックは合成信号の単体テストで検証します(ノイズだけでは点灯しない、段差・振動では点灯する、など)。
7. S26 Ultra基準の高密度UIを成立させる方法
- 行の高さは約20〜22dp、文字は13〜14spの等幅(数字は等幅字形)にします。一般的な6.8インチ級の縦画面なら、ヘッダーを除いても35行前後が入る見込みです。
- 余白・区切り線・カードは使わず、行の背景を1行おきにわずかに変えるだけにします。
- 列幅は文字数から計算して固定し、数値の変化で横位置が揺れないようにします。
- 幅が十分ある画面(タブレット、横向き)は自動で複数列にします(列数 = 画面幅dp ÷ 約360)。機種は判定せず、画面幅だけで決めます。
- 最終的な行の高さと文字サイズは、S26 Ultraの実機結果を見てから決めます。
8. 詳細画面のグラフ
- グラフライブラリは使わず、Compose Canvasで自前描画します。依存を増やさず、描画も軽く済みます。
- 時間軸は20秒の流れる表示です。チャンネルごとに色を分けます。on-change型は階段状、トリガー型は縦線マーカーで描きます。
- Y軸は自動スケールにし、広げるときは即座に、縮めるときはゆっくり変えます。軸が暴れないようにするためです。
- PAUSE はグラフと値をスナップショットで止めます。裏では記録を続け、RESUMEで最新に戻ります。
FLAG_SECUREは付けないので、OSのスクリーンショットをそのまま撮れます。
9. 表示設定と保存
- 保存にはJetpack DataStoreを使います。中身は、形式バージョン・並び順(キーの配列)・非表示にしたキーの集合です。
- 初めて見るキー(OS更新や動的センサーで増えたもの)は、表示ONのまま末尾に追加します。今回の起動で見当たらないキーも削除せずに残します。
- 初期順序はカテゴリ順にします(動き → 位置 → 環境 → その他・未知)。同じカテゴリ内はOSが返した順です。「振ったら上の方がまとめて光る」配置になります。
- 非表示にしたセンサーは購読も止めます(推奨)。電池・CPUの節約になり、挙動のおかしいVendorセンサーやWake-upセンサーを止める手段にもなります。
- ドラッグ&ドロップは、Compose用の並べ替えライブラリ(Apache-2.0)を使うか自作するかを選べます。確実性を優先してライブラリを推奨します。
10. Export形式
JSONを正、CSVも出力することを推奨します。お手元のExcelで複数端末のファイルを並べて比べるなら、CSVの方が圧倒的に楽です。
- 保存先はStorage Access Framework(保存先を選ぶ画面)で指定します。ストレージ権限は要りません。共有シートにも対応します。
- ファイル名:
AF-SensorMonitor_<Manufacturer>_<Model>_<yyyyMMdd-HHmmss>.json/.csv - JSONの構成:
{
"format": "af-sensormonitor-inventory", "formatVersion": 1,
"app": {"name": "AF-SensorMonitor", "version": "1.0.0"},
"exportedAt": "2026-…+09:00",
"device": {"manufacturer","brand","model","device","product","hardware",
"androidRelease","sdkInt","securityPatch","fingerprint"},
"sensorCount": N,
"sensors": [{"index","key","name","vendor","version","type","stringType",
"resolution","maximumRange","power","minDelayUs","maxDelayUs",
"reportingMode","isWakeUp","isDynamic","id","fifoReserved","fifoMax",
"additionalInfoSupported","directReportRateLevel",
"observed": {"eventsReceived","valuesLength","lastAccuracy"}}]
}
observed(Export時点までの受信状況)は、比較のときに「実際に値を出したか」「値は何個か」を見分けるのに役立ちます。- ANDROID_IDやシリアル番号など、端末を個別に特定できる情報は含めません。
11. マスコットの配置案
視認性を最優先にして、3か所だけに出します。
- ヘッダー左端の小さなアイコン(約24dp):通常と反応中の2状態です。たとえば全体で5個以上のセンサーが同時に反応したら「驚き」顔になります。計器盤の行には一切かぶりません。
- アプリアイコン
- 表示設定画面の最下部:バージョン表記と一緒に出します。
素材は透過PNGかSVGで、2状態を暗い背景・明るい背景の両方でご用意いただけると助かります。ライセンス方針の「ブランド素材は許諾しない」の扱いにも該当する見込みです。
12. 1.0.0から削るもの・最初から入れるもの
最初から入れる:
- 20秒の履歴の常時保持
- one-shot・on-change・権限・購読失敗の各状態表示
- 縦固定と画面ON維持
- 幅に応じた複数列
- 非表示時の購読停止
- JSONとCSVのExport
- 動的センサーへの追従
- メイン画面のHOLD
入れない:
- メイン画面の行ごとのミニグラフ
- 記録・ロギング
- 取得頻度の設定
- テーマ切り替え(ダークテーマに固定。計器盤らしく、有機ELでも見やすいため)
- SensorAdditionalInfo の表示
- 身体センサーの権限取得
- マスコットのアニメーション(2状態を超えるもの)
実装計画(承認後)
- プロジェクト作成:作成手順に従い、
AF-SensorMonitor/を作ります。 - AGENTS.md(Android節のみ)、HISTORY.md、.gitignore を用意し、ローカルでgit initして初回コミットします。 - 資料集のREADME・プロジェクト別文書・CHANGELOGに登録します。 - バージョン設定元はVERSION.txtにし、そこからGradleの versionName と versionCode を生成します。 - APKの出力先はbin/Android/Release-<Version>/AF-SensorMonitor-<Version>.apk、署名鍵は.local/android-signing/(Git管理外)に置きます。 - センサー層:列挙、キーの生成、標準TYPEの名前・単位・書式表、ライフサイクル連動の購読管理、トリガー型、権限状態、動的センサー、リングバッファ。
- 反応判定:アルゴリズムと合成信号の単体テスト。
- メイン画面:高密度の行、HOLD、複数列。
- 詳細画面:Canvasグラフ、PAUSE、メタ情報の表。
- 表示設定画面:DataStore、並べ替え、全表示、初期順序、JSON・CSVのExport。
- マスコット:素材の枠だけ先に用意し、素材が届いたら差し替えます。
- 検証: - エミュレーターで検証します。仮想センサーと、拡張コントロールでの値操作が使えるので、実機の事前調査なしに開発できます。 - その後、Release APKをPixel 7 Proで確認し、S26 Ultraなどはご指示を受けてから入れます。 - 実機の結果を見て密度を調整します。
ご確認いただきたい点
- S26 Ultraへの転送:AF-MilitaryShogiでは「S26はユーザーの実戦用で、転送は明示指示の時だけ」という運用でした。本ソフトでも同じ扱い(開発はPixel 7 Pro、S26は指示を受けてから)でよいでしょうか。
- 版数:規約では最初のビルド成果物が1.0.0です。実機を見ての密度調整は1.0.1以降として記録する形でよいでしょうか。
- UIの言語:センサー名と値の表示は英語、メニュー(全表示・初期順序など)は日本語、でよいでしょうか。
- 権限:歩数計(
ACTIVITY_RECOGNITION)は、詳細画面からユーザーが操作したときだけ許可を求める形で1.0.0に入れ、身体センサーは🔒表示だけにする案でよいでしょうか。 - タブレットのAndroidバージョン:minSdk 26(Android 8.0)で足りるか確認させてください。お聞きしたいのはOSのバージョンだけで、センサー構成は伺いません。
- 並べ替えのライブラリ:外部ライブラリ(Apache-2.0)の利用はよいでしょうか。
承認をいただくまで、コード作成とプロジェクト作成には進みません。このレビューを共有しやすいページにまとめることもできます。
👤 筆者 2026-09-25 19:36
🤖 Claude Code 2026-09-25 19:39
両端末の接続を確認しました(S26 Ultra:Android 16・1080×2340・450dpi、Pixel 7 Pro:Android 17)。続けてプロジェクトの骨組みを作ります。
ビルド設定ができました。次にセンサー層(型カタログ・キー・反応判定・履歴)を書きます。
センサー層の純粋ロジック(型カタログ・キー・反応判定・履歴・数値書式)を書き終えました。続けて端末のSensor APIと接続する部分を書きます。
センサー層・設定保存・Exportができました。これから画面(メイン・詳細・表示設定)を書きます。
メイン画面ができました。次は詳細画面(20秒グラフとPAUSE)です。
初回ビルドを試しています(SDKのパス解決でエラーが出たので調べています)。
Escaping of local.properties was wrong; fixing.
デバッグビルドが通りました。両実機にインストールして、実際に何個のセンサーが出るかを見ます。
S26 Ultraは45個、Pixel 7 Proは39個を返しました。S26では現状スクロールが出る(1行17dpの下限に当たる)ので、画面を確認して調整します。
S26 Ultraで45個全部がスクロールなしで1画面に収まりました(行の高さ15.9dp、文字11.4dp)。Pixel 7 Proの画面も確認します。
続けて単体テストを書きます(反応判定・名前の短縮・キー・書式・配置・Export)。
テスト24件がすべて通りました。実機に入れ直し、静止状態で誤点灯がないかを数回の撮影で確かめます。
詳細画面(グラフ・メタ情報)と設定画面は正常に表示されています。表示ON/OFFとドラッグ並べ替えを試します。
表示OFFと並べ替えが効いています。再起動しても設定が保持されるか、非表示のセンサーの購読が止まっているかを確認します。
権限ダイアログが表示されました。許可はせず、閉じてメイン画面に戻します。
Release APKができました(署名検証済み)。中身(debuggableでないこと・版数)を確認してから、両実機にRelease版を入れます。
規約とHISTORYを書きました。念のため、Release版でも詳細画面と表示設定画面が開くかをPixelで確認します。
Release版でも詳細画面・PAUSE・表示設定が動きました。最後にEXPORTの保存経路(SAF)をPixelで1回通します。PixelのDownloadsにJSONが1つ保存されます。
Git Bashがパスを書き換えたので、パス変換を無効にして取り直します。
EXPORT(JSON)はRelease版で保存でき、内容も正しいことを確認しました(39センサー、形式v1)。READMEを書いてGitの初回コミットに進みます。
gradlew の改行がCRLFに変わらないよう .gitattributes を足してからコミットします。
最後に、規約資料集へ本プロジェクトを登録します(README一覧・プロジェクト別文書・CHANGELOG)。
AF-SensorMonitor 1.0.0 のRelease APKが両実機で確認できる状態になったので、ここで作業を止めます。実際に振る・回す・光を当てる・磁石を近づけるなどの刺激で反応するかは、まだ人の手で確かめていません。そこはお手元での確認をお願いします。
実機が返したセンサー
事前の調査はせず、アプリ自身に数えさせた結果です。
| 端末 | センサー数 | 表示 |
|---|---|---|
| Galaxy S26 Ultra(Android 16) | 45 | 縦1画面に全部入り、スクロールなし(行の高さ15.9dp・文字11.4dp) |
| Pixel 7 Pro(Android 17) | 39 | スクロールなし(行の高さ19.0dp) |
- S26 Ultra:Samsung独自のセンサーのうち約20個(
BACK_TAP、POCKET_MODE、CAR_CRA_DETEなど)は、OSが購読を受け付けずN/Aと表示されます。一覧には出ますが値は読めません。これも「何が出てくるか」の結果の一部として、除外せず残しています。 - Pixel 7 Pro:Google独自のセンサー(
GYRO_TEMPERA、CAMERA_VSYNC4個、SINGLE_TOUCHなど)も一覧に出ます。
S26の完成条件(全表示で縦1画面にスクロールなし)は満たしています。ただ文字は11.4dp相当と小さめです。読みにくければ相談させてください。行の高さと文字の大きさは画面の高さから自動で決めるので、機種ごとの調整はしていません。
実機で確かめたこと
- Release版(両端末):起動とメイン画面の表示。静止中は動き系センサーが誤って点灯せず、照明が変わった瞬間に照度系の3つ(LIGHT / LIGHT_IR / LIGHT_CCT)が同時に点灯しました。
- Release版(Pixel):詳細画面、PAUSE / RESUME、表示設定画面。EXPORTのJSONは、Pixelの「ダウンロード」フォルダーに保存して中身が正しいことを確認しました。このファイルは残してあります。
- デバッグ版(Pixel):表示のON/OFF、ドラッグでの並べ替え、再起動後も設定が残ること、非表示にしたセンサーの購読が止まること、歩数系を開いたときに権限を求める画面が出ること。
- 単体テスト:24件すべて成功しました。反応判定は、手ぶれ程度のノイズでは点灯せず、振り続けても数秒で消えないようにテストで調整しています。
- 未確認:CSVの保存(出力内容自体はテストで確認済み)、許可した後に歩数計が動くか。
ご報告しておくこと
- Pixelで権限を求める画面を戻るボタンで閉じたところ、デバッグ版に「身体活動」の権限が許可された状態になってしまいました。すぐに取り消しています。デバッグ版もその後アンインストール済みで、Release版には影響ありません。
- S26には本アプリのRelease版だけを入れました。開発用のデバッグ版はアンインストールしてあり、他のアプリやデータには触れていません。S26での開発作業はここで終わりなので、USBは外していただいて大丈夫です。次に接続するのは次回のReleaseビルドを入れるときです。
- マスコットは素材待ちのため、仮の図形を入れています。場所はヘッダー左端、アプリアイコン、表示設定の最下部で、多数のセンサーが同時に反応すると表情が変わります。
成果物
- APK:
bin/Android/Release-1.0.0/AF-SensorMonitor-1.0.0.apk(SHA25633AF447C…) - ローカルGitで初回コミット済み(
42f7a84)。GitHubへのpushはしていません。 - 規約とプロジェクトの説明:AGENTS.md、HISTORY.md、README.md
- 規約資料集に登録しました:プロジェクト別文書、README.mdの一覧、CHANGELOG.md。
SHG03とAndroidタブレットへの展開はご指示を待ちます。
👤 筆者 2026-09-25 20:24
🤖 Claude Code 2026-09-25 20:24
ORIENTのラップアラウンドは、半分は仕方がなく、半分は直せます。
仕方がない部分(データ側):方位角(AZIMUTH)は0〜360°の円周の値なので、北をまたぐと359°の次が0°になります。センサーが返す値そのものがこうなので、数値表示で359→0と飛ぶのは正しい動作です。
直せる部分(グラフの描き方):縦線が上端から下端まで走るのは、359°と0°の点をそのまま線で結んでいるためです。角度のチャンネルでは、前の点との差が180°を超えたら線を切って描き直すようにできます。Y軸が397〜−146に広がっているのも、この縦線を含めて範囲を取っているのが一因です。値を連続させる方法(0→−1→…と続ける)もありますが、軸が0〜360°から外れて分かりにくくなるので、線を切る方式がよいと考えます。なお、反応判定のほうは内部で角度をつないで計算しているので、北をまたいでも誤って点灯しません。
別に見つかった問題:4枚目で、振っている最中に ACCEL-U は●なのに ACCEL が○のままです。原因はこちらの判定方式にあります。
- 詳細画面のとおり、S26のACCELは約540Hzで値が届いています。要求した約50Hzより速いのは、他のアプリやシステムがもっと速い頻度を要求していると、その速さで全員に配られるためと考えられます。起動直後のInventoryでも約8秒で3,659件でした。
- 今の判定は「1サンプル前との差」で見ています。頻度が10倍になると1サンプルあたりの動きは1/10になりますが、センサーのノイズは同じなので、速いセンサーほど反応が見えにくくなります。
- 直し方:前回の値との差ではなく、少なくとも約20ms前の値との差で判定します。そうすれば50Hzでも540Hzでも同じ感度になり、機種判定も要りません。
どちらも1.0.0の調整の範囲で直せます。直してよければ、Pixel 7 Proで確認したうえでRelease APKを作り直します。S26に入れるには再接続が必要なので、その時点で改めてお声がけします。
👤 筆者 2026-09-25 20:34
🤖 Claude Code 2026-09-25 20:35
PPIスコープ式は、方位角(AZIMUTH)には特に合っていて、よい案だと思います。
PPI式の利点
- 角度を円周上の位置で表すので、0°と360°は同じ場所に来ます。北をまたいでも軌跡は途切れず、ラップアラウンドの問題そのものが消えます。
- 半径を時間にします(外周が現在、中心が20秒前)。回した軌跡が渦のように内側へ流れていくので、何秒前にどちらを向いていたかが一目で分かります。
- 「回した」という操作と見た目が直結するので、今回の企画の趣旨に合います。
向かない値もある
- ピッチ(−90〜+90°)は円周の量ではありません。円に描くと半周しか使わず、読みにくくなります。
- ロール(−180〜+180°)は円周の量ですが、方位と同じ円に重ねると混ざって分かりにくくなります。
- 案:PPIは方位専用にし、ピッチとロールは従来の時間グラフで表示します。時間グラフも、差が180°を超える点で線を切ります。
適用するセンサー
- 対象:ORIENT、ROTVEC、GEOROT、GAMEROT(ROT系は四元数から換算した方位で描く)、HEADING。
- GAMEROTの方位は北ではなく、起動時の向きが基準です。このセンサーだけ円の上端を「N」ではなく「0°」と表示します。
- MAGなど他のセンサーは従来どおりの時間グラフです。
注意点
- スマホを立てると(ピッチが±90°付近)、方位角は数学的に不安定になって大きく飛びます。今回の縦線の一部はこれが原因の可能性があります。これはPPIにしても防げません。「立てると方位が暴れる」という現象がそのまま見える、と割り切る形になります。
- 詳細画面はPPIの円(直径およそ240dp)と時間グラフの2段になり、少し縦に長くなります(スクロールで対応)。
- PAUSEはPPIとグラフの両方を同時に止めます。
1.0.0の調整として、前回挙げた2点(高頻度センサーの反応判定、角度グラフの線切り)と合わせて入れてよいでしょうか。承認をいただければ実装してPixelで確認し、Release APKを作り直したところでS26の再接続をお願いします。
👤 筆者 2026-09-25 20:42
🤖 Claude Code 2026-09-25 20:42
はい。方位角のPPI表示に、高頻度センサーの反応判定と角度グラフの線切りを合わせた3点を入れます(ピッチ±90°付近で方位が暴れるのは許容として扱います)。実装してPixelで確認します。
ビルドが通りました。単体テストを追加します(500Hzでも50Hzと同じように反応すること、角度の分割、角度差の計算)。
28件すべて通りました。念のため、修正前の方式(間隔0)に一時的に戻すとこのテストが失敗するかも確かめます。
方位のPPI表示・高頻度センサーの反応判定・角度グラフの線切りの3点を入れ、作り直したRelease APKをPixel 7 Proにインストールしました。実際に回したときの軌跡と、振ったときのACCELの点灯はまだ確かめていないので、Pixelで確認をお願いします。
入れたもの
- 高頻度センサーの反応:変化量を、18ms以上離れた値どうしで測るようにしました。S26のACCELのように約540Hzで届くセンサーも、約50Hzのセンサーと同じ感度で点灯するはずです。
- 単体テストを追加し、500Hzでも50Hzと同じように反応することを確かめました。
- 修正前の方式ではこのテストが失敗する(500Hz側の反応が0件)ことも確認しています。
- PPI式の方位表示:ORIENT・ROTVEC・GAMEROT・GEOROT・HEADINGの詳細画面で、方位を円の上に表示します。方向が角度、外周が現在、中心が20秒前です。
- 北をまたいでも軌跡は途切れません。
- GAMEROTだけは北が基準ではないので、上端を「0°」と表示します。
- ピッチ±90°付近の大きな跳びは、円を横切る線にならないよう線を切ります。
- 時間グラフの線切り:ピッチ・ロールは下の時間グラフに出し、0/360°をまたぐ点は線で結びません。
- 値の色は、方位=赤、ピッチ=緑、ロール=青でグラフとそろえました。
- ORIENTの方位に付いていた「+」記号は外しました。
Pixelで確認したこと:Release版で、ORIENTとROTVECの詳細画面が正しく表示されることを確認しました。端末は置いたままなので、軌跡は針と重なった状態までしか見ていません。単体テストは28件すべて通っています。
Pixelで見ていただきたい点
- ORIENTかROTVECを開いて端末を水平に回したとき、北をまたいでも軌跡が途切れずに円周をたどるか。
- メイン画面で振ったとき、ACCELがACCEL-Uと同じように点灯するか。
S26について:いまはS26が未接続なので、S26に入っているのは最初のRelease APKのままです。Pixelで問題なければ、次のRelease APKを入れるときにS26をつないでください。版数は1.0.0のまま(ご指示のとおり完成工程内の調整)です。
コミットは 7f860c0 と de210e6 で、ローカルのみ(pushなし)。HISTORY.mdとREADMEにも反映しました。
👤 筆者 2026-09-25 21:09
🤖 Claude Code 2026-09-25 21:09
切り出し範囲を自動で求めています(大きい絵と小さいプレビューが重なっているため、つながった領域ごとに分けます)。
背景をぼかし画像にすると、周囲に紫のにじみが出てしまいました。背景は、アイコンの縁の暗い色の単色に変えます。
アイコンは円形・角丸どちらのマスクでも欠けなくなりました。リソースの参照を差し替え、マスコットの表示を画像に切り替えます。
ビルドが通りました。Release APKを作り直してPixelに入れ、表示を確認します。
製品固有の規約(素材の扱い)を追記したので、規約資料集のプロジェクト別文書とCHANGELOGにも反映します。
マスコットとアプリアイコンをご提供の素材に差し替え、Pixel 7 Proを更新しました。反応時にクロさんの表情が切り替わるかと、ホーム画面でのアイコンの見え方は、まだ確かめていないので実機で見ていただけますか。
素材の保管
- 2枚の原本は
Reference/UserProvided/に移しました(「ユーザー提供リソースフォルダ」は、AF-MilitaryShogiと同じこの形にしています)。原本は編集せず、SHA256をREADME.mdに記録しました。 - 切り出しには透過版を使い、
Tools/make_assets.pyで再生成できるようにしました。小さいプレビューの髪の端が入り込む部分は、自動で取り除いています。
使い方
- ヘッダー左端(28dp)
- 静かなとき:平常心の画像を、輝度60%に落として表示します。
- センサーが4個以上同時に強く反応したとき:「センサー暴れ」に切り替わります。
- 表示設定の最下部(40dp):平常心をそのまま表示し、バージョンを添えています。
- アプリアイコン:提供アイコンの角丸の内側を中央に置き、縁をぼかして背景の暗い色(#110F29)になじませました。
- 最初は画面いっぱいに置きましたが、円形のマスクで右側の波形が欠けたので小さくしています。
- 円形・角丸どちらのマスクでも欠けないことを、合成画像で確認しました。
変えていないもの:ヘッダーの高さは同じなので、行の配置は変わりません。S26の45行も1画面に収まったままです。機能の変更はありません。表示のためのコード変更は、マスコットを図形から画像に替えた部分だけです。
確認できたこと
- Release APK(1.0.0のまま再ビルド)をPixelにインストールし、起動と、ヘッダー・表示設定のマスコット表示を確認しました。単体テストは28件すべて通っています。
記録:コミット 6d88c8f(ローカルのみ)。HISTORY.md・AGENTS.mdと規約資料集(プロジェクト別文書・CHANGELOG)に、素材の保管場所と、ブランド素材なのでコードのライセンスには含めないことを記録しました。
S26は未接続のため、S26のアプリは最初のRelease版のままです。
👤 筆者 2026-09-25 21:28
🤖 Claude Code 2026-09-25 21:28
タブレットにはRelease APKを入れて起動しました。シャープ機は、まだ接続が許可されていないため転送できていません。
- タブレット(モデル P40HD_EEA):Release APKをインストールし、起動したことを確認しました。ご指示どおり転送と起動だけで、画面やセンサー構成は見ていません。
- シャープ機:
unauthorized(USBデバッグ未許可)の状態で、何も転送していません。端末に「USBデバッグを許可しますか」のダイアログが出ていれば、「許可」を押してください。許可されたら、同じように転送と起動を行います。
👤 筆者 2026-09-25 21:33
🤖 Claude Code 2026-09-25 21:33
SHARP SHG03にもRelease APKを入れて起動しました。起動したアプリのプロセスが動いていることまで確認しています。画面やセンサー構成は見ていないので、何が出てくるかは端末で直接見てください。
これでタブレットとSHG03の両方で、Release 1.0.0が起動した状態です。
👤 筆者 2026-09-25 21:50
🤖 Claude Code 2026-09-25 21:51
SHG03の画面で、単位の「rad/s」「steps」が右端で切れています。タブレットは最下段の行が下のバーに少しかかっているように見えます。原因を確かめるため、両端末の画面設定と行の位置を読み取ります(読み取るだけで、何も操作しません)。
SHG03の切れの原因は分かりました。タブレットの最下段は、途中で接続が外れたため確認できていません。
実機の結果について
- SHG03(18個):加速度・ジャイロ・地磁気と、それらを組み合わせた姿勢系(ROTVEC・ORIENTなど)、近接、照度、歩数と、基本の部品はひととおり揃っています。独自センサーは「STEP_TIME」1つだけです。
- タブレット(32個):実際に動いている部品は加速度センサー1つだけのようです。ジャイロと地磁気センサーがないので、それらを元に計算するROTVEC・ORIENT・GRAVITYなども一覧に出ません。照度・近接もありません。
- 残りの約30個は、加速度だけで作る「検出器」です(TAP、FLIP、FACE_UP_DOWN、ELEVATOR、CHOPCHOPなど)。多くは通常版とWake-up版(w)が2つずつ並んでいます。
- これらの「---」はN/A(購読失敗)ではありません。購読には成功していて、該当する動作が起きるのを待っている状態です。ARMEDも同じく発火待ちです。タブレットを伏せる・裏返す・タップするなどで反応するものがあるかもしれません。
見つかった表示の不具合
- SHG03で単位が切れる:行の文字には、Material標準の文字間隔(1文字ごとに0.5sp)が入っていました。文字幅の計算にこの間隔を入れていなかったのが原因です。
- 行数が少なく文字が大きくなる端末ほど、行の幅が足りなくなります。SHG03は18行なので文字が大きく、44文字×0.5sp=約22dpあふれて単位が切れました。
- S26は文字が小さいので切れず、Pixelはぎりぎり収まっていました。
- 直し方:行の文字間隔を0にし、幅の計算にも少し余裕を持たせます。機種ごとの調整は不要です。
- タブレットの最下段がバーにかかって見える:画面下のタスクバーの分を取り切れていない可能性があります。ただ、今回はタブレットの接続が切れていて確認できませんでした。次に接続したときに実際の行の位置を測って確かめます。
SHG03の修正は1.0.0の調整として入れてよいでしょうか。直したRelease APKを作ったら、Pixel・SHG03・タブレットに入れて確認し、タブレットの最下段もそのとき合わせて調べます。
👤 筆者 2026-09-25 21:56
🤖 Claude Code 2026-09-25 21:56
ビルドとテストが通りました。Release APKを作り、3台に転送して確認します。
3台とも、単位が最後まで表示され、最下段の行も正しい高さになりました。タブレットの詳細画面で、見出しの折り返しも直ったか確認します。
見出しは1行に収まりました。HISTORYに記録してコミットします。
見切れを直したRelease APKを3台(Pixel 7 Pro・SHG03・タブレット)に転送し、どの端末でも表示が崩れていないことを画面で確認しました。3台ともクラッシュはありません。
直したこと
- SHG03で単位が切れる:行の文字に標準の文字間隔(1文字ごとに0.5sp)が入っていたのが原因でした。行の文字間隔を0にし、幅の計算にも少し余裕を持たせました。SHG03でも「rad/s」「steps」が最後まで表示されます。
- 最後の行がつぶれる:各行の高さの端数が1行ずつ切り上がって積み重なり、最後の行が押しつぶされていました。行の高さを整数ピクセルにそろえ、タブレットの最後の行も他と同じ高さで表示されるようになりました。S26の最後の行が窮屈だったのも同じ原因です。
- タブレットで詳細画面の見出しが折り返す:タブレットは文字サイズ設定が1.3になっているため、「DIRECT REPORT」などが2行に折れていました。見出しの列幅を文字サイズ設定に比例させ、1行に収まるようにしました。
確認した画面
- 3台すべてで、単位が切れないことと、最後の行が他の行と同じ高さであることを確認しました。
- タブレットでは詳細画面も開き、見出しが1行に収まることを確認しました。ただ「ADDITIONAL INFO」は値との間が1文字分とやや詰まっています。
その他
- タブレットの STATIONARY が「×1」になっていました。机に置いた状態で「静止」を検出したようです。
- 版数は1.0.0のままで、コミットは
9082fda(ローカルのみ)です。 - S26は未接続なので、S26のアプリはまだ最初のRelease版のままです。次に接続したときに、この版を入れます。
👤 筆者 2026-09-25 22:15
🤖 Claude Code 2026-09-25 22:16
タブレットはELEVATORの詳細画面が開いたままでした。戻るボタンでメイン画面に戻してから撮り直します。
S26にも最新のRelease APKを転送し、4台そろって同じ版で動いていることを確認しました。4台の画面を並べた画像は上に送っています(ファイル:build/devcheck/AF-SensorMonitor-1.0.0-4devices.png)。
確認結果
- 4台とも同じRelease APKです(各端末に入ったファイルのハッシュが一致)。起動・メイン画面の表示とも問題なく、クラッシュもありません。
| 端末 | センサー数 | 画面 |
|---|---|---|
| Galaxy S26 Ultra | 45 | 27/45表示(下記) |
| Pixel 7 Pro | 39 | 全表示、1画面 |
| SHARP SHG03 | 18 | 全表示、1画面 |
| タブレット P40HD_EEA | 32 | 全表示、1画面 |
気づいた点
- S26の表示が27/45:表示設定で18個が非表示になっていたので、そのまま撮っています。設定には触れていません。STEPSも429歩と表示されていて、歩数の権限は許可済みのようです。全45個が1画面に収まることは初回に確認済みで、行の配置は変わっていません。この版で全表示の画面も撮り直すなら、表示設定の「ALL」を押していただければ撮影します。
- タブレットの STATIONARY が「×173」:静止検出の発火を数えた回数です。机に置いたままだと約1秒ごとに発火し続けるので、数字が増えていくのは想定どおりです。
- 未解決の不具合:タブレット(文字サイズ設定1.3)の詳細画面で、タイトル2行目(正式名称)が下の状態行に重なっています。上部の帯の高さを固定していたためで、文字サイズに合わせて伸びるようにすれば直ります。修正する場合は、4台への再転送が必要です。
HISTORY.mdに4台での確認結果と、この未解決の点を記録しました(コミット 4a2500a、ローカルのみ)。
👤 筆者 2026-09-25 22:29
🤖 Claude Code 2026-09-25 22:29
お疲れさまでした。AF-SensorMonitor 1.0.0の開発は、ここで一旦終了にします。
今の状態
- 4台(S26 Ultra・Pixel 7 Pro・SHG03・タブレット)に同じRelease APK 1.0.0が入っています。
- コミットはローカルのみです(最新
a7b03bc)。GitHubへのpushやリポジトリ作成はしていません。 - HISTORY.mdの1.0.0には「開発一旦終了、使用・ブログ記事化の間に気づいた点を修正予定」と記録しました。
再開するときのメモ
- 未解決の不具合が1つあります。タブレットのように文字サイズ設定が大きい端末で、詳細画面のタイトル2行目が状態行に重なる件です。
- 1.0.0は今回で完成とする扱いなので、この後の修正は1.0.1以降になる見込みです。版数は再開時に相談させてください。
- S26は今も接続したままなので、外していただいて大丈夫です。次に接続するのは、次のRelease APKを入れるときです。
ブログ記事化の中で気づいた点があれば、いつでもお知らせください。



























