3_Androidタブレット対応_実装案.md の「9. フェーズ別実装計画 / フェーズ1」「13. 実装開始時の最初の作業」を、実行可能な単位まで分解したもの。フェーズ1のみを対象とする。フェーズ2以降は実装案の粒度のまま、フェーズ1の結果(方式確定・却下条件)を踏まえて別途手順化する。
フェーズ1は完了した(詳細はdocs/decisions/p3-phase1-spike.md)。実行してみて、この手順の想定と異なっていた点は次のとおり。
winget install Google.PlatformToolsから始める必要があったgradle wrapperコマンドでwrapperを生成した。Android Studioは一度も起動していないgradle.propertiesにandroid.newDsl=false / android.builtInKotlin=falseを設定し、従来のorg.jetbrains.kotlin.android + org.jetbrains.kotlin.plugin.compose構成を採用した。この判断はこの手順にもとの実装案にも書かれていなかったandroid-v12.3.1(実装案の最低条件android-v11.8.8を大きく超える)でもpmtiles://asset://...はstd::runtime_error: incorrect header checkで毎回SIGABRTした。.pmtilesをAPK内で無圧縮化するnoCompress指定も単独では解消せず、アプリ内部ストレージへ初回コピーするfile://方式への切り替えが実質必須だった。根本原因は未特定adb installは初回INSTALL_FAILED_USER_RESTRICTEDで失敗した。原因は(1)画面スリープ中はインストール許可ダイアログが出ずサイレントに拒否扱いになる、(2)HyperOS特有の開発者向けオプション「Install via USB」「USBデバッグ(セキュリティ設定)」を追加で有効化する必要がある、の2点。どちらもこの手順にもとの実装案にも記載がなかったdev.drogger.tabletについて、実際は確認を待たずそのまま採用して実装を進めた。正式名称は引き続き未確定手順ごとに実施者を明記する。
| 項目 | 内容 | 未確定の場合 |
|---|---|---|
| 対象タブレット | 機種、Android API level、CPU ABI、空き容量 | ユーザーが実機で確認し、この手順のステップ1に記録する |
| DG-PRO1RWS | 現物とAndroidタブレットとのペアリング可否 | ステップ7で初めて検証する。事前ペアリングは不要 |
| 開発環境 | Android Studio、JDK、Android SDKがユーザー環境(またはCI)にインストール済みか | 未インストールなら Android Developers: Android Studioのダウンロード に従いユーザーが用意する |
| パッケージ名 | 実装案では「実装開始時に決める」としていた未決定事項 | ステップ2で仮の値 dev.drogger.tablet を使う。本採用前にユーザー確認が必要(下記「未決定事項」参照) |
adb shell getprop ro.build.version.sdk でAPI levelを取得するadb shell getprop ro.product.cpu.abilist でCPU ABIを取得するこの結果で minSdk が変わる可能性があるため、ステップ2より前に済ませる。
apps/android-tablet/ に、実装案 4節 のディレクトリ構成に沿った最小プロジェクトを作る。この時点ではMapLibreやBluetoothは組み込まず、空のCompose画面だけを作りビルドを通す。
build.gradle.kts)dev.drogger.tablet(仮。ユーザー確認後に変更可)apps/android-tablet/README.md に、JDK・Android SDK・Gradle・AGPの採用バージョンを記録する(./gradlew --version の出力を転記)./gradlew assembleDebug が成功することを確認するこの段階のcommit境界: 「空のプロジェクトがビルドできる」で1コミット。
app/build.gradle.kts に MapLibre Native Android の依存を追加する。バージョンは実装案の確定事項(L21)である android-v11.8.8 以上を満たす最新安定版を使う。着手時点で ./gradlew dependencies またはMaven Centralで実際に取得可能な最新版を確認してから固定する(本手順作成時点でのリリース履歴上の目安は11.11.0系。13.x系はデフォルトrendererがVulkanに変更されているため、フェーズ1で13.x系を使う場合はレンダラー互換性も確認対象に追加する)./gradlew assembleDebug が通ることを確認するapps/android-tablet/README.md に記録する実装案 5節 に従い、tools/map/static/ から以下を app/src/main/assets/map/ へコピーする。このフェーズでは自動同期タスク(SyncMapAssets、フェーズ4予定)は作らず、手作業コピーとし、コピー元・コピー日をREADMEに記す。
offline-basemap.pmtilesfude-overlay.geojsonoffline-tiles/gsi-seamlessphoto/(zoom 15〜17分のみ、P2実績と同じ範囲)map-config.json の値(背景設定・出典)を読み、Android側のstyle定義に必要な値のみ転記する(JS由来のstyle生成コードは移植しない)ui/MapScreen.kt に、AndroidView で MapView をComposeへ組み込むだけの最小実装を作る(現在地・Bluetoothはまだ扱わない)pmtiles://asset://map/offline-basemap.pmtiles を vector source として読み込み、簡易styleで表示する(実績: 実機でSIGABRTし、file://方式への切替が必須だった。「実績との差分」参照)fude-overlay.geojson をGeoJSON source + line layerとして追加する./gradlew assembleDebug と ./gradlew lint が通ることを確認するこの段階のcommit境界: 「地図表示コードが入るがまだ実機確認していない」で1コミット。
./gradlew installDebug でインストールする(Claudeが手順は用意するが、実機接続を要するため実行はユーザー)。実績: 画面がスリープしていると許可ダイアログが出ずサイレント拒否される。また対象機種(HyperOS)では開発者向けオプションの「Install via USB」「USBデバッグ(セキュリティ設定)」も別途有効化しないとINSTALL_FAILED_USER_RESTRICTEDになるadb logcat にPMTiles関連のエラー(invalid header、decompression error等)が出ない分岐: asset直読みで問題が出た場合のみ、実装案の退避策(4節L98)に従い、PMTilesをアプリ内部ストレージへ初回コピーするfile://方式に切り替えて再検証する(Claudeが切替コードを用意し、ユーザーが再度実機確認)。
offline-tiles/gsi-seamlessphoto/ をXYZ raster sourceとしてstyleに追加するコードを実装するAndroidManifest.xml に BLUETOOTH_CONNECT 権限を追加し、実行時許可リクエストの最小実装を作るDG-PRO1RWS... または RWS... を選ぶ簡易UI(本実装ではなくログ確認用の暫定UI)を作る00001101-0000-1000-8000-00805F9B34FB)でRFCOMM socketを作成し、connect() を呼ぶ最小コードを書くBLUETOOTH_CONNECT 許可後にDG-PRO1RWSを選択し、生NMEA数行がログに表示されることを確認する各ステップ後に維持すべき検証をフェーズ1完了時にまとめて再実行する。
./gradlew test
./gradlew lint
./gradlew assembleDebug
この時点でJVM testは0件でもよい(フェーズ2でparser等のtestを追加する)。lintで警告が出た場合は、致命的でない限りフェーズ1では記録のみでよい。
docs/decisions/ に記録する(P2の p2-map-prototype.md に相当するP3版として、フェーズ1完了時に新規作成する。ファイル名は未定のため、このタイミングで決める)dev.drogger.tablet のまま実装を進めた。正式なドメイン/組織名が決まったら変更する12.3.1 に確定した(13.x系のVulkanデフォルト化を避けるため12.x系最終版を採用。詳細はdocs/decisions/p3-phase1-spike.md)