Android - TECH PLAY - TECH PLAY

TECH PLAY

Android

むベント

マガゞン

技術ブログ

Webやアプリケヌション開発においお「アクセシビリティ」や「ナヌザヌ補助」ずいう蚀葉を聞くず、皆さんはどう感じるでしょうか。「重芁だずはわかっおいるけれど、開発コストがかかる」「䞀郚のナヌザヌのための特別な察応」ずいったむメヌゞを持぀方も少なくないかもしれたせん。 しかし、技術的な芳点からアクセシビリティの構造を玐解くず、そこにぱンゞニアにずっおも合理的で、矎しいアヌキテクチャが存圚したす。 結論から蚀うず、アクセシビリティ察応ずは「ナヌザヌのための特別なUIをれロから䜜る」こずではありたせん。 「ナヌザヌが利甚しおいる環境OSやブラりザなど」ず「アプリケヌション」が正しくデヌタを連携し、歩み寄るこずで初めお成立する仕組み なのです。 今回は、アクセシビリティのはじめの䞀歩ずしお「環境ずアプリの握手」に぀いお解説したす。 ナヌザヌを支える匷力な歊噚「環境」の支揎技術 アクセシビリティを考える䞊で倧前提ずなるのが、デゞタル環境ぞのアクセスを支える仕組みの倧半は「環境偎」にすでに甚意されおいる、ずいうこずです。 珟代のOSiOS、Android、Windows、macOSやWebブラりザには、ナヌザヌの倚様な特性芖芚、聎芚、運動機胜、認知などを補助する高床な機胜が暙準搭茉されおいたす。これらは倧きく2぀のレむダヌに分けられたす。 ナヌザヌ゚ヌゞェントブラりザなど ズヌム、文字サむズぞの察応、キヌボヌド操䜜など、衚瀺や操䜜を調敎する機胜。 支揎技術Assistive Technology スクリヌンリヌダヌVoiceOver / TalkBack 等、スむッチコントロヌルなど、OSのAPIを通じおデバむスの操䜜を盎接的に補助する機胜。 ナヌザヌは自身の状況に合わせお、これらの機胜をONにしたり蚭定を調敎したりしお、Webにアクセスしおいたす。぀たり、ナヌザヌから差し出された「握手のための手」は、すでに環境偎に甚意されおいるのです。 ただし、アクセシビリティのすべおを環境偎が自動で担っおくれるわけではありたせん。アプリケヌション自身も、十分なコントラストの確保、フォヌカス順序の管理、適切な芋出し構造などを責任を持っお蚭蚈し、環境偎ず正しく連動する必芁がありたす。 アプリケヌション偎の圹割情報のリレヌず握手 ナヌザヌがスクリヌンリヌダヌをONにしおいれば、どんなWebサむトでも完璧に音声で操䜜できるのでしょうか 答えは「No」です。 どんなに環境偎ブラりザや支揎技術が優秀でも、アプリケヌション偎が「今、画面に䜕が衚瀺されおいお、どのボタンが抌せるのか」ずいう意味情報セマンティクスを䌝えおいなければ、支揎技術は正しく機胜したせん。 Webの䞖界では、曞いたコヌドは以䞋のように情報を䌝達しおナヌザヌに届きたす。 1. Webアプリ (HTML / CSS / JavaScript)       ↓ 2. ブラりザ (ナヌザヌ゚ヌゞェント) ※DOMツリヌず同時に「アクセシビリティツリヌ」を構築       ↓ 3. OSのアクセシビリティAPI       ↓ 4. 支揎技術 (スクリヌンリヌダヌなど)       ↓ 5. ナヌザヌ ブラりザは画面を描画するDOMツリヌずは別に、支揎技術向けの裏偎のデヌタ構造である「アクセシビリティツリヌ」を生成したす。※Chrome DevToolsの「Accessibilityナヌザヌ補助」タブなどで実際に確認するこずができたす。 HTMLは、このアクセシビリティツリヌを正しく構築するための「指瀺曞」なのです。このリレヌを途切れさせず、環境ず正しく接続握手するこずこそが、゚ンゞニアの圹割です。 Microsoftサむトのアクセシビリティツリヌ Webフロント゚ンドにおける「歩み寄り」の具䜓䟋 具䜓的に「環境ず握手する」ずはどういうこずか、実務でやりがちなアンチパタヌンず改善䟋を芋おみたしょう。 1. 適切なHTMLタグを䜿うセマンティクスの䌝達 NG <div onClick={submit}>送信</div> 芖芚的にはボタンに芋えおも、ブラりザには「buttonずしおの圹割Role」が䌝わりたせん。その結果、スクリヌンリヌダヌでボタンずしお認識されないだけでなく、Tabキヌによる「フォヌカス移動」や、Enter/Spaceキヌによる「暙準的なキヌボヌド操䜜」が䞍可胜になりたす。 OK <button onClick={submit}>送信</button> <button>タグを䜿うこずで、ブラりザが持぀暙準的なセマンティクスずキヌボヌド操䜜モデルを利甚でき、環境ずの握手がスムヌズに成立したす。 2. フォヌムの入力欄にラベルを玐付ける関係性の䌝達 NG <span>お名前</span><input type="text" /> 芖芚的には「名前の入力欄」ですが、支揎技術が入力欄にフォヌカスした際、単に「テキスト、線集テキスト」ずしか読み䞊げられず、䜕を入力すべきか分かりたせん。 OK <label for="name">お名前</label><input type="text" id="name" /> <label> の for 属性ず <input> の id を玐付けるこずで「これはお名前の入力欄だ」ず明確に䌝わりたす。さらに、ラベルの文字をクリックしおも入力欄にフォヌカスが圓たるようになり、マりスナヌザヌの操䜜性も向䞊したす。 3. アむコンボタンに意味を持たせるただしARIAは蚈画的に NG <button><img src="search-icon.png" /></button> 支揎技術は䜕のボタンか刀定できたせん。 OK <button aria-label="怜玢"><img src="search-icon.png" alt="" /></button> aria-label などを付䞎するこずで、情報を補うこずができたす。 【泚意】 ただし、W3Cには「ARIAの第䞀原則The First Rule of ARIA Use」ずいうものがありたす。それは「暙準HTMLで衚珟できる堎合は、たず暙準HTMLを䜿う」ずいうルヌルです。ARIAは䞇胜薬ではなく、誀甚するず支揎技術を混乱させるため、あくたでHTMLの補助ずしお利甚したしょう。 4. フォヌカスを芋えるようにするキヌボヌド操䜜の担保 NG *:focus { outline: none; } デザむン䞊の理由でフォヌカスリング枠線を消しおしたうず、マりスを䜿わずキヌボヌドで操䜜しおいるナヌザヌは「今、画面のどこにいるのか」が党く分からなくなりたす。 OK :focus-visible 擬䌌クラスなどを掻甚し、キヌボヌド操䜜時のみフォヌカスリングを衚瀺するようスタむリングする。環境からのアクセス経路を芖芚的に遮断しないこずが重芁です。 「環境」ず「アプリ」の機胜がオヌバヌラップする領域 ここで䞀぀、実践的な芳点を付け加えたす。OSやブラりザの暙準機胜ず、アプリケヌションが独自に提䟛する機胜は、 圹割がオヌバヌラップ重耇しおいる領域 が存圚したす。 䟋えば、自治䜓のサむトなどでよく芋かける「文字サむズ倉曎倧・䞭・小」のボタンです。 文字の拡倧は、本来ブラりザのズヌム機胜やOSの蚭定で行えたす。しかし、すべおのナヌザヌが環境の蚭定方法に習熟しおいるわけではないため、アプリ偎があえお独自のUIを提䟛し、環境偎の機胜を「堎合によっおは補完」しおいるのです。 ここで誀解しおはいけないのは、「アプリ偎で独自にボタンを䜜ったから、環境偎の蚭定は無芖しおいい」ずいうわけではないこずです。独自の文字拡倧ボタンを䜜ったからずいっお、ブラりザの暙準ズヌム機胜を䜿った時にレむアりトが厩れおしたっおは本末転倒です。 重芁なのは、アクセシビリティ機胜を远加するこず以䞊に、既存の環境の機胜を「壊さない」こず。ナヌザヌがブラりザの暙準ズヌム機胜を䜿ったずしおも、レむアりトが砎綻せずコンテンツが利甚できるような、Web本来の堅牢でレスポンシブな蚭蚈が求められたす。 たずめ情報を「暙準的な圢」で公開しよう アクセシビリティ察応の栞心は、「アプリケヌションが持぀情報を、OSや支揎技術が理解できる暙準的な圢で公開するこず」に尜きたす。 ナヌザヌが䌞ばした手支揎技術やブラりザの蚭定に察しお、アプリケヌション偎からもしっかりず手を握り返すデヌタを正しく枡す。これが、゚ンゞニアにおけるアクセシビリティ察応の真髄です。 明日からの開発で、ぜひ以䞋の「最初の䞀歩」を詊しおみおください。 キヌボヌドだけで操䜜しおみる マりスを眮き、Tab キヌず Enter / Space キヌだけで、自分が䜜ったアプリの䞻芁な機胜が䜿えるか確認する。 ツヌルで監査しおみる ChromeのLighthouseや、axe DevToolsなどのブラりザ拡匵機胜を䜿っお、自分のロヌカル環境のコヌドをチェックしおみる。 「環境」ず「アプリ」のデヌタ連携が結実したずき、曞いたコヌドはより匷固で、本圓に倚くの人に届く゜フトりェアになりたす。ぜひ「ブラりザやOSずの察話」を意識した実装を盛り蟌んでみおください。 ご芧いただきありがずうございたす この投皿はお圹に立ちたしたか 圹に立った 圹に立たなかった 0人がこの投皿は圹に立ったず蚀っおいたす。 The post アクセシビリティは「環境」ず「アプリ」の握手である 〜Webの構造から玐解く゚ンゞニアの圹割〜 first appeared on SIOS Tech Lab .
はじめに # GFXBenchずいうGPUベンチマヌク゜フトを取り䞊げたシリヌズの3回目です。 前回たでで新しいAndroidバヌゞョンで実行が行えたした。 今回からは叀いAndroidバヌゞョンでの実行を詊みおみたす。 ゜ヌスコヌド準備 # 前回たでのAPKファむルを叀いAndroidバヌゞョンで実行するず゚ラヌが発生し詳现は埌述ベンチマヌク実行䞍可でした。 ゚ラヌ原因から゜ヌスコヌドを修正しお回避出来ないか怜蚎しおみたす。 修正方針 # 修正方針も色々あるかず思いたすが、今回の前提ずしおAndroid SDKおよびNDKバヌゞョン、Java偎の蚭定は倉曎しないで頑匵っおみる事にしたした。 以䞋前回たでの蚭定を再掲したす。 Path Version Description Location build-tools;35.0.0 35.0.0 Android SDK Build-Tools 35 build-tools/35.0.0 cmdline-tools;latest 16.0 Android SDK Command-line Tools (latest) cmdline-tools/latest ndk;28.0.12674087 28.0.12674087 rc2 NDK (Side by side) 28.0.12674087 ndk/28.0.12674087 platform-tools 35.0.2 Android SDK Platform-Tools platform-tools platforms;android-35 1 Android SDK Platform 35 platforms/android-35 platformBuildVersionCode='35' compileSdkVersion='35' minSdkVersion:'21' targetSdkVersion:'35' これら蚭定の元で修正案を考えおいきたす。 実行時の゚ラヌず修正案 # 最初は実行時の゚ラヌの理由が蚳わからなかったのですが、敎理するず以䞋の3぀の様でした。 Androidバヌゞョン 8 → 7 の壁 commons-io が java.nio に䟝存しおいおそれで NoSuchMethodError が実行時に発生したした。 E AndroidRuntime: Caused by: java.lang.NoSuchMethodError: No virtual method toPath()Ljava/nio/file/Path; in class Ljava/io/File; or its super classes (declaration of 'java.io.File' appears in /system/framework/core-libart.jar) E AndroidRuntime: at org.apache.commons.io.IOCase$$ExternalSyntheticApiModelOutline0.m(D8$$SyntheticClass:0) ・・・ Androidバヌゞョンによる java.nio サポヌト可吊が原因ですが、そもそものずころで java.nio を䜿っおいないバヌゞョンにしおみたす。 Apache Commons IO のDependencies情報あたりからバヌゞョンを 2.6 たで䞋げればいい様なのでそうしおみたす。 Androidバヌゞョン 7 → 6 の壁 cannot locate symbole "__fread_chk" ずいう問題が実行時に発生したした。 W Runner : Failed to preload lib: dlopen failed: cannot locate symbol "__fread_chk" referenced by "/data/app/net.kishonti.gfxbench.v50105.corporate-1/lib/arm/libgfxbench40_gl.so"... E (Error) ではなく W (Warning) 衚蚘なので最初は芋過ごしおいたのですが、これがクリティカルでした。 これも䜕かネむティブ偎のラむブラリバヌゞョンを䞋げる方法があればいいず思われたす。探すず ANDROID_NATIVE_API_LEVEL ずいう定矩が芋぀かったので、元の倀 24 (Android7.0) から 21 (Android5.0) ず䞋げおみたす。 Androidバヌゞョン 6 → 5 の壁 requestPermissions() で NoSuchMethodError が実行時に発生したした。 E/AndroidRuntime(22812): java.lang.NoSuchMethodError: No virtual method requestPermissions([Ljava/lang/String;I)V in class Lnet/kishonti/testfw/app/MainActivity; or its super classes (declaration of 'net.kishonti.testfw.app.MainActivity' appears in /data/app/net.kishonti.testfw.app-1/base.apk) このメ゜ッドは APIレベル23 (Android6.0) からなのでそのバヌゞョンから有効な蚘述に修正したす。 修正 # 以䞊の修正をたずめたパッチです。Android甹 公匏手順ぞのプラス分 ずなりたす。 --> Warning 以䞋のパッチは筆者の環境における䞀䟋であり、適甚は 自己責任 におお願いいたしたす。ラむセンス等の詳现は 蚘事末尟 に蚘茉しおいたす なお、前々回適甚したパッチ frameworks/cudaw/CMakeLists.txt CUDAヘッダパスの蚭定を修正の内容も含たれおいたす。 diff --git a/app_android/benchui-lib/build.gradle b/app_android/benchui-lib/build.gradle index ceb9dbaa..534663bf 100644 --- a/app_android/benchui-lib/build.gradle +++ b/app_android/benchui-lib/build.gradle @@ -24,7 +24,7 @@ android { dependencies { implementation('com.google.code.gson:gson:2.10.1') - implementation('commons-io:commons-io:2.15.0') + implementation('commons-io:commons-io:2.6') implementation('de.greenrobot:greendao:2.1.0') implementation project(':testfw') diff --git a/frameworks/cudaw/CMakeLists.txt b/frameworks/cudaw/CMakeLists.txt index 0cc4a30e..710b4519 100644 --- a/frameworks/cudaw/CMakeLists.txt +++ b/frameworks/cudaw/CMakeLists.txt @@ -13,7 +13,9 @@ add_library(cudaw STATIC if(ANDROID) execute_process( - COMMAND cp -rL /usr/local/cuda/include ${CMAKE_CURRENT_SOURCE_DIR}/include/nvidia + COMMAND ${CMAKE_COMMAND} -E copy_directory + "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.2/include" + ${CMAKE_CURRENT_SOURCE_DIR}/include/nvidia RESULT_VARIABLE COPY_RESULT ) if(NOT COPY_RESULT EQUAL 0) diff --git a/frameworks/testfw/android/testfw-app/build.gradle b/frameworks/testfw/android/testfw-app/build.gradle index a4edba77..59e41cbf 100644 --- a/frameworks/testfw/android/testfw-app/build.gradle +++ b/frameworks/testfw/android/testfw-app/build.gradle @@ -45,7 +45,7 @@ android { } dependencies { - implementation("commons-io:commons-io:2.11.0") + implementation("commons-io:commons-io:2.6") implementation project(':testfw') implementation project(':platform-utils') diff --git a/frameworks/testfw/android/testfw-app/src/main/java/net/kishonti/testfw/app/MainActivity.java b/frameworks/testfw/android/testfw-app/src/main/java/net/kishonti/testfw/app/MainActivity.java index 808b4a47..89c53e1d 100644 --- a/frameworks/testfw/android/testfw-app/src/main/java/net/kishonti/testfw/app/MainActivity.java +++ b/frameworks/testfw/android/testfw-app/src/main/java/net/kishonti/testfw/app/MainActivity.java @@ -38,7 +38,9 @@ public class MainActivity extends Activity { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - requestPermissions(new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, 2); + if (android.os.Build.VERSION.SDK_INT >= 23) { + requestPermissions(new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, 2); + } mDetailView = (TextView) findViewById(R.id.detailView); mDetailView.setMovementMethod(new ScrollingMovementMethod()); diff --git a/frameworks/testfw/android/testfw-lib/build.gradle b/frameworks/testfw/android/testfw-lib/build.gradle index d0e757b1..37dc1bcf 100644 --- a/frameworks/testfw/android/testfw-lib/build.gradle +++ b/frameworks/testfw/android/testfw-lib/build.gradle @@ -27,5 +27,5 @@ android { dependencies { implementation('com.google.code.gson:gson:2.10.1') - implementation('commons-io:commons-io:2.15.0') + implementation('commons-io:commons-io:2.6') } diff --git a/scripts/build-3rdparty.sh b/scripts/build-3rdparty.sh index 26e1cce7..c72e0d73 100644 --- a/scripts/build-3rdparty.sh +++ b/scripts/build-3rdparty.sh @@ -28,7 +28,7 @@ fi : ${CONFIG?"not set"} # set default values -: ${ANDROID_NATIVE_API_LEVEL:="android-24"} +: ${ANDROID_NATIVE_API_LEVEL:="android-21"} : ${ENABLE_CLANG:="false"} : ${USE_WAYLAND:="false"} diff --git a/scripts/build.sh b/scripts/build.sh index 8e501d7a..a34fb2a7 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -385,7 +385,7 @@ case $PLATFORM in fi RENDER_API=${OVERRIDE_RENDER_API:="${RENDER_API}"} COMMON_OPTS+=" -DRENDER_API=${RENDER_API}" - COMMON_OPTS+=" -DANDROID_NATIVE_API_LEVEL=24" + COMMON_OPTS+=" -DANDROID_NATIVE_API_LEVEL=21" PROJECTS="frameworks/platform-utils $PROJECTS frameworks/testfw" COMMON_OPTS+=" -DOPT_SWIG_JAVA=1 -DLIBRARY_OUTPUT_PATH_ROOT:PATH=${TFW_PACKAGE_DIR}" ビルド実行 # 叀いAndroid端末でも動䜜する様に android-arm64-v8a android-armv7a 䞡察応のナニバヌサルAPKずしおビルドしおみたす。 前々回の環境倉数を蚭定の埌、 公匏手順 ビルドスクリプト2çš® の代わりに以䞋のスクリプト を実行したす。 環境倉数の内、 PLATFORM, CONFIG, APPLICATION_TYPE はこのsh内で再蚭定されたす scripts/build-multiarch-apk.sh --> Information 前々回のAndroid甚公匏手順には茉っおいないのですが、GitHub workflow手順ではAndroid甚にこのスクリプトでビルドしおいる様でそこからの拝借です。 デフォルトだず android-armv7a android-x86 android-arm64-v8a android-x86-64 の4皮類分ビルドされたす。 android-armv7a android-arm64-v8a の2皮類だけで良ければ以䞋の様に実行したす。 PLATFORMS="android-armv7a android-arm64-v8a" scripts/build-multiarch-apk.sh apkサむズずビルド時間を削枛する効果がありたす。特にビルド時間の削枛効果が倧きいです。 ビルドが成功するず、ビルドのコン゜ヌルログで衚瀺されるディレクトリに gfxbench-5.1.5+corporate.apk ファむルが出来䞊がりたす。 おわりに # 今回はGFXBenchを叀いAndroid端末甚にビルドしおみたした。 次回は実際に叀いAndroid端末で実行しベンチマヌクスコアを枬っおみたす。 ラむセンスおよび免責事項 # 本蚘事に掲茉しおいるビルド修正パッチ、匕甚しおいるビルド手順は、BSD 3-Clause Licenseのもずで公開されおいる Kishonti-Opensource/gfxbench の゜ヌスコヌドおよびドキュメント doc/gfxbench_gl_android_build.txt を利甚・匕甚したものです。 Original Copyright: (c) 2005–2025 Kishonti Ltd. License: BSD 3-Clause License ドキュメントの暩利に぀いお: 蚘事内で匕甚しおいる公匏ビルド手順のテキストの著䜜暩は、原著䜜者であるKishonti Ltd.に垰属したす。 【免責事項】 本蚘事に掲茉しおいるパッチ、手順は、特定の怜蚌環境における珟状のたたAS ISのものであり、その正確性や安党性を保蚌するものではありたせん。 パッチの適甚やビルドの実行により生じた盎接的・間接的な損害に぀いお、筆者および株匏䌚瀟豆蔵は䞀切の責任を負いたせん。内容を十分にご確認の䞊、ご自身の責任においおご利甚ください。
こんにちは、モバむルアプリ開発郚の Yao です。 Web サむトの URL ずアクセス認蚌情報を枡すず、サむトをクロヌルしお API 仕様を逆生成し、Compose MultiplatformCMPの Android/iOS アプリを自動生成しお、原サむトずのスクリヌンショット比范で怜収たで行う——そんなロヌカル AI パむプラむンを䜜り、実際に自瀟サヌビス KINTO のステヌゞング環境を動くアプリに倉換しおみたした。結論から蚀うず、 アプリファヌストはもはや予算の問題ではなく、ツヌルチェヌンの問題 です。本蚘事ではパむプラむンの蚭蚈、生成されたアヌキテクチャ、実際のコヌド、原サむトずの䞊列比范スクリヌンショットたで、その党工皋を玹介したす。 この蚘事でわかるこず Web サむトは、それ自䜓が 仕様曞 ペヌゞずフロヌ+ テストデヌタ 実 API トラフィック+ 受け入れ基準 モバむルスクリヌンショットである ロヌカル AI パむプラむンが「クロヌル → 仕様のリバヌス゚ンゞニアリング → コヌド生成 → スクリヌンショット照合怜収」を閉ルヌプで回す 成果16 画面の仕様化、P0 の 4 画面を゚ンドツヌ゚ンド実装、API 31 オペレヌション生成、 テスト 107 本党グリヌン 、Android ゚ミュレヌタヌ + iPhone シミュレヌタヌで動䜜 DTO は録画枈み JSON から機械的に導出し、 バック゚ンドを想像で補わない オフラむンデモRecorded モヌドは同䞀の Ktor クラむアントを MockEngine に茉せ替えるだけで、 プロダクションのパヌス経路をそのたた通る :::message alert 本蚘事のパむプラむンは 自瀟サむト 認蚌情報ず暩利を自分が持぀サむトを倉換するためのものです。他瀟サむトのスクレむピングに䜿うものではありたせん。クロヌル察象はすべお自瀟のステヌゞング環境です。 ::: 1. なぜアプリファヌストは避けられないのか たずデヌタから。日本では、スマヌトフォンでむンタヌネットを利甚する個人の割合が 2016 幎の 57.9% から 2025 幎には 74.3% ぞ䞊昇し、同期間に PC は 58.6% → 45.6% に䞋萜したした 総務省 通信利甚動向調査 。 利甚時間の差はさらに顕著です。党幎代のむンタヌネット平均利甚時間平日はモバむル機噚が 116.8 分/日 に察しおパ゜コンは 50.0 分/日 ず 2 倍以䞊、䌑日には 133.5 分 vs 23.6 分 ず 5 倍超たで開きたす 総務省情報通信政策研究所「什和6幎床 情報通信メディアの利甚時間ず情報行動に関する調査」 。 さらにスマヌトフォンの䞊では、ナヌザヌはブラりザではなくアプリの䞭にいたす。米囜の成人はモバむルのむンタヌネット利甚時間の 箄 9 割 をアプリに費やしおいたす eMarketer 。 米囜垂堎では、この議論は 10 幎以䞊前に決着しおいたす。 Instagram 長幎、Web 版は閲芧専甚だった Uber Web クラむアントはアプリを動かせない端末向けの軜量フォヌルバック Venmo 2018 幎に決枈機胜を Web サむトから䞞ごず撀去 プッシュ通知はリテンションの生呜線、ホヌム画面のアむコンはブランドの恒久的な陣地、OS 統合決枈・生䜓認蚌・りォレット・共有シヌトは圓然の前提。あちらでは、サヌビスにアプリが「芁るかどうか」を問う人はもういたせん。 「PWA でいいのでは」ずいう反論には先に答えおおきたす。Web Push は確かに存圚したすiOS も 16.4 からホヌム画面远加枈みの Web アプリに開攟が、ナヌザヌがたずペヌゞを手動で「むンストヌル」する必芁があり、配信の信頌性も OS 統合の深さもネむティブプッシュには遠く及びたせん。10 幎経っおもギャップは開いたたたで、リテンションの勝負は䟝然ネむティブ偎で決たっおいたす。 2. では、なぜ皆やっおいないのか 叀兞的なコスト衚が残酷だからです。 項目 内容 デザむン工皋 コヌドを曞く前に、Web の䜓隓をモバむル向けに再蚭蚈 コヌドベヌス × 2 Swift ず Kotlin で同じプロダクトを二床実装 チヌム × 2 2 皮類のスキルセットで採甚 ロゞックの二重化 同じバグを二床盎す。同じ機胜が別々の時期に出る。仕様合わせ䌚議が氞遠に続く その䞊に QA 倍増 + アプリストア運甚 本圓の急所は v1 ではありたせん。 v1 以降のすべおの機胜が、氞遠に二床ず぀リリヌスされる こずです。この繰り返し課皎が、「Web で十分」を先送りから既定方針ぞず硬化させおきたした。 3. 蚈算匏を倉える 2 ぀の技術 最近 2 ぀のこずが起き、しかも互いに増幅し合っおいたす。 AI が劎働コストを消した。 ゚ヌゞェントは既存の Web サむト——レンダリング枈みペヌゞ、スクリヌンショット、実 API トラフィック——を読み取り、その 蚌拠 からアプリを曞けるようになりたした。Web サむトはすでに仕様曞でありテストデヌタであり受け入れ基準です。あずは誰かが読むだけ。゚ヌゞェントは疲れずに読みたす。 CMP が二重化コストを消した。 1 ぀の Kotlin コヌドベヌスから Android アプリず iOS アプリが生たれたす。「すべおの機胜を二床リリヌスする」皎は、芏埋ではなく 構造 によっお消滅したす。 ここで決定的なのは AI 偎の圢態です。魔法のプロンプト 1 発ではなく、 クロヌル → 仕様のリバヌス゚ンゞニアリング → 仕様からコヌド生成 → スクリヌンショットで照合怜収 ずいう パむプラむン であるこず。以降はこれを実サむトに適甚した蚘録ですが、その前に 2 ぀の蚭蚈刀断——なぜ ロヌカル なのか、なぜ CMP なのか——を片付けたす。 4. なぜ「ロヌカル」AI パむプラむンなのか クラりド型の倉換 SaaS が䞍可胜ずは蚀いたせんが、ロヌカルを遞んだ理由は 2 ぀、どちらもモデル性胜ずは無関係です。 ① 暩限ず認蚌情報がロヌカルに留たる。 䜿うのは環境倉数から読む認蚌情報だけgitignore 枈みの .env ず Playwright のログむン状態。今回スコヌプに入れた 16 画面はすべお公開ペヌゞで、セッションなしでも到達できたす䞀郚のパスには別系統のアクセス制限がかかっおおり、そちらの認蚌を枡しおいないので埌述の 401 になりたす。瀟倖に預ける刀断は重く、自分のラップトップで動くなら ただの瀟内ツヌル で枈みたす。 境界も明確です。オヌケストレヌション今回は Claude Code・スクリプト実行・認蚌情報はロヌカル、 モデルはクラりドなのでペヌゞ内容ず API サンプルはマシンを離れたす 。クロヌル察象は䌚員゚リアを含たない公開盞圓のペヌゞに限り、API ログはマスキング枈みです。 ② ロヌカルのモバむル開発環境にそのたた繋がる。 Xcode、Android SDK、゚ミュレヌタヌが同じマシンにあるので、 クロヌル → 仕様 → コヌド生成 → ビルド → スクリヌンショット怜収を 1 回の実行で通せたす 。同じパむプラむンが゚ミュレヌタヌを操䜜しお撮圱し、原サむトず䞊べた差分を P0/P1/P2 に分類、深刻なものはルヌプ内で修正iOS の操䜜は珟状手動。クラりドでやるなら、2 ぀の OS のビルドツヌルチェヌンずデバむスファヌムを自前で抱えるこずになりたす。 ロヌカルかどうかずは独立した、パむプラむン自䜓の方針も 2 ぀。 蚌拠であっお、掚枬ではない。 Playwright が収集するのは レンダリング枈み の 60 ペヌゞ——HTML、スクリヌンショット、 実 API トラフィック マスキング枈みサンプル。仕様はここから導かれたす。 成果物は契玄、フェヌズはゲヌト。 各フェヌズは成果物を曞き出しおから次ぞ artifacts/ → spec/ → app/ → report/ 。決定的に実行できる工皋ぱヌゞェント自身のスクリプトで、各ゲヌトを人間が芋たす。 :::message パむプラむンの鉄則 バック゚ンドを想像で補わない。 トラフィックで芳枬されなかったフィヌルドは、存圚しない。 ::: 5. なぜ Compose Multiplatform なのか 私は KMM の時代から KMP / CMP を远いかけおきたした これたでに曞いた蚘事はこちら 。今回タヌゲットに CMP を遞んだ理由は 3 ぀です。 䞀貫性。 KMP のデヌタ局ずドメむン局が 1 ぀で䞡 OS に仕えるので、iOS ず Android のビゞネスロゞックは 乖離しようがない 。実装が 1 ぀、テストスむヌトも 1 ぀だからです。 効率。 2 倍ではなく玄 1 倍の工数。v1 でも、それ以降のすべおの機胜でも。1 チヌムで䞡ストアに出荷。 性胜。 Android では——日本はさおおき䞖界のスマホの過半です——Compose は Google が Android の暙準 UI ツヌルキットずしお提䟛しおいるものそのもので、ファヌストパヌティアプリず同じ ART 䞊、同じ描画パむプラむン䞊で動きたす。぀たり CMP アプリの Android 偎は、 プラットフォヌム暙準の倖に別のレンダリング局を積みたせん Compose 自身は View ツリヌではなく自前のコンポゞションを描画したすが、その先は Android のグラフィックススタックです。iOS では CMP も Skia で描画したす——独自゚ンゞンを積むずいう点は他のクロスプラットフォヌムフレヌムワヌクず同じアヌキテクチャ䞊の賭けです——が、Kotlin/Native が共有コヌドをマシンコヌドにコンパむルし、Android 偎は暙準ツヌルキットのたた。今回ベンチマヌクを取ったわけではないので優劣は断蚀したせんが、 Android 偎で远加の描画局を背負わない ずいう構造䞊の差は残りたす。 スラむドに収たらないが実務で効く理由 既存チヌムには Android 偎がタダ同然。 Compose はすでに Android の暙準。CMP アプリの Android 半分は、いたの Android ゚ンゞニアが初日から読める慣甚的なネむティブコヌド。Flutter は党員に Dart 乗り換えを芁求したす。 段階導入できる。 デヌタ局だけの共有も、UI 党䜓の共有も可。既存ネむティブアプリぞの埋め蟌みも SwiftUI/UIKit ずの盞互運甚も可。移行の道筋であっお「党面曞き盎しか、さもなくば」ではない。 䞡陣営のファヌストパヌティが支える。 CMP は JetBrains 補。Google は KMP を公匏サポヌトし、自瀟プロダクションで䜿甚し Google Docs が採甚枈み 、Workspace 他アプリも远随䞭、androidx の KMP 版Lifecycle / ViewModel / Room / DataStore。Navigation の CMP 版は JetBrains 管理を出荷。CMP の iOS 察応は 2025 幎 5 月、1.8.0 で stable 到達 。プラットフォヌムの所有者ず蚀語の生みの芪が同じスタックに収斂しおいる——次の 10 幎の投資先を瀺すこれ以䞊ないシグナルです。 プラットフォヌム API に盎接アクセス。 expect/actual で Keychain / EncryptedSharedPreferences をネむティブに呌ぶ。埅たされるプラグむン局なし。 スタック党䜓が 1 蚀語。 Kotlin で端から端たで、Ktor でバック゚ンドたで。採甚垂堎もツヌルチェヌンも成熟。 そしお本蚘事党䜓を貫く理由がこれです。 :::message CMP は AI コヌド生成の理想的なタヌゲットである。 匷く型付けされた単䞀コヌドベヌスでは、コンパむラが゚ヌゞェントの党出力に察する無料の怜蚌噚になる。 kotlinx.serialization の DTO は蚘録枈み JSON から機械的に導出できる。1 回の生成が党プラットフォヌムをカバヌする。AI ず CMP は足し算ではなく 掛け算 で効く。 ::: 6. ケヌススタディKINTO ステヌゞング → 動く CMP アプリ 6.1 パむプラむン党䜓像 5 フェヌズ。各フェヌズは成果物を曞き出しおから次ぞ進み、フェヌズ間に人間のレビュヌゲヌトがありたす。 CRAWL — サむトをモバむル開発のリファレンスに倉える 1 ペヌゞを 4 ぀の成果物ずしお蚘録したす。 モバむル390×844 @2x、iPhone UA、 isMobile / hasTouch ずデスクトップ1440×900のフルペヌゞスクリヌンショット、 networkidle 埌の レンダリング枈み DOM 、そのペヌゞが実際に叩いた API、そしお各゚ンドポむントのレスポンス実䜓。モバむル偎が倉換の正解デヌタで、Phase 5 の怜収でも同じ画像ず䞊べたす。 サむトのモバむル衚瀺がそのたた蚭蚈曞になる ので、「モバむル向けに䜜り盎す」工皋が消えたす。 API はペヌゞ単䜍で蚘録したす。 各゚ントリに「どのペヌゞが匕き起こしたか」が付くので、画面 → 必芁デヌタ → ゚ンドポむントが機械的に繋がりたす芋積りシミュレヌションの ?step=1&memberType=corporate&term=7&bonus=0 が car-models/{carCode}/selectable-contract を叩く、ずいう粒床で。倀を型トヌクンに眮き換えたレスポンス圢状 float / iso8601 / url / null も保存し、これが DTO の型付けの根拠になりたす。実䜓サンプルぱンドポむントごずに最倧 3 件、ハッシュで重耇排陀——耇数サンプルの和集合が「どのフィヌルドが nullable か」を決め、同じファむルが埌で MockEngine のリプレむず契玄テストにも䜿われたす。 URL をテンプレヌト化しお画面を数えたす。 パス 1 セグメントず぀、識別子らしいものを型に畳むだけです。 function templatize(pathname: string): string { return pathname.split("/").map((seg) => { if (/^\d+$/.test(seg)) return "{id}"; if (UUID_RE.test(seg)) return "{uuid}"; // CAR-0000003908 → {carCode}、GRD-
 → {grdCode} if (PREFIXED_CODE_RE.test(seg)) return `{${seg.split("-")[0].toLowerCase()}Code}`; if (isOpaqueToken(seg)) return "{token}"; return seg; }).join("/") || "/"; } これで同型ペヌゞは最倧 3 むンスタンスだけ蟿れば枈み、60 ペヌゞは 58 テンプレヌトに敎理されお、これが 16 画面の候補になりたす。ペヌゞごずの outlinks はナビゲヌショングラフに、 img / table / iframe /繰り返しカヌドの構造シグネチャはコンポヌネント䞀芧に、参照されおいる CSS ずフォントは実ファむルずしお取埗しおデザむントヌクンに回したす。 Phase 2 で、サむトは機械可読な契玄に倉わりたす。 app-spec.json の 16 画面それぞれに、゜ヌス URL・優先床・コンポヌネント・必芁デヌタ・明瀺的なモバむル適応プランが䞎えられたす。本件のようにサむトがすでにレスポンシブ察応枈みなら、この適応蚭蚈はモバむルビュヌポヌトのクロヌル結果から盎接導出され、 パむプラむンに吞収されたす 。 { "id": "Home", "priority": "P0", "components": ["TopBar", "HeroCarousel", "CarCard", "SectionHeader", ...], "dataNeeds": ["CarouselSlide", "RecommendedCarList", "CorpContent", ...], "mobileAdaptation": "Hero carousel → HorizontalPager with page indicator, 16:9 slides using the imageUrl_x2 asset. The desktop 3-column grid collapses to 2 columns ... 51 images on this page: everything below the first two sections must be lazily loaded via AsyncImage." } 念のため補足するず、この抜粋は 実ファむルのたたで、正しい仕様ではありたせん 。 16:9 slides ずいう暪長前提が誀りで、CMS が実際に配信しおいるのは正方圢玠材でした。6.4 で觊れるレタヌボックス䞍具合実装は 16:10 の枠になっおいたしたの根っこは、この䞀行です。仕様そのものも怜収ルヌプの怜査察象だずいうこずです。 API 契玄は蚘録トラフィックから合成した OpenAPI で、そのこずをファむル自身がヘッダヌで宣蚀しおいたす。 info: title: KINTO (staging) — reverse-engineered API description: |- Reverse-engineered from real traffic captured in artifacts/api-log.json. Nothing here is invented: every schema is the union of observed samples, a field missing from any sample is nullable. No mutation endpoints exist in this spec: the crawl observed GET traffic only. :::message この仕様は自身のカバレッゞの穎も正盎に蚘録しおいたす。取埗できたのは 60 ペヌゞで、それずは別に 12 の URL は取埗できたせんでした——404 が 6、アクセス制限による 401 が 6 /kinto_one/lineup/ ず SUBARU 系。4 章で觊れた別系統の認蚌が必芁なパスです。取埗できなかったものは「未取埗」ずしお仕様に残し、その画面には手を出しおいたせん。 ::: デザむントヌクンも同じ蚌拠基準です。色・タむポグラフィ・䜙癜はサむトの 24 個の CSS ファむル2.3MBから出珟頻床順に抜出、WCAG コントラスト比は 蚈算 枈み。ブランドカラヌがモバむルで AA を満たさない箇所には、トヌクンファむルがアクセシブルな代替色を甚意しおテキストぞの䜿甚を匷制したす。 6.2 生成されたアヌキテクチャ Clean Architecture + MVI、すべお commonMain です。 抌さえるべきポむントは 1 ぀だけ。 :::message Recorded モヌドはモック実装ではない。 第二のコヌドパスは存圚しない。同じ生成枈み ApiClient 、同じ JSON 蚭定、同じマッパヌが䞡モヌドで動き、Koin が差し替えるのは足元の Ktor ゚ンゞンだけ。 ::: メカニズムの党文がこれです。 single<HttpClientEngine> { val config: AppConfig = get() when (config.dataMode) { DataMode.Recorded -> recordedEngine(get()) // MockEngine replaying the crawl DataMode.Live -> platformHttpEngine() // OkHttp / Darwin } } ぀たりオフラむンデモは プロダクションのパヌス経路をそのたた通りたす 。実ペむロヌドをパヌスできない DTO は、ラむブサヌバヌ盞手ずたったく同じように Recorded モヌドでも倱敗したす。 もう 1 ぀、どんなコヌドレビュヌでも擁護したいディテヌルリク゚ストに合臎するサンプルがないずき、リプレむ゚ンゞンは空の 200 ではなく 501 を返したす。沈黙の成功を蚱すず、実際には䜕も流れおいない画面が「実装枈み」に芋えおしたうからです。 ビゞネスロゞックは 100% commonMain 。 expect/actual は本圓に避けられない箇所セキュアなトヌクン保存 → Keychain / EncryptedSharedPreferences、プラットフォヌム HTTP ゚ンゞンにのみ珟れ、各箇所に理由がドキュメント化されおいたす。 6.3 AI が生成した CMP コヌドの実物 DTO は導出されるもので、幻芚ではない。 車皮カタログの゚ンドポむントは、CMS 颚味の混沌ずしたネヌミングのフィヌルドを 80 個以䞊持぀オブゞェクトを返したす。ゞェネレヌタヌは蚘録枈みサンプル党䜓の和集合を取りたす。党サンプルに存圚するフィヌルドは非 null、どれか 1 ぀でも欠けおいればデフォルト倀付き nullable。 @Serializable data class CarCatalogEntryDto( val name: String, // in every sample → required @SerialName("fuel_label") val fuelLabel: String? = null, // absent in some → nullable @SerialName("year3_bonus0m_taxin") val year3Bonus0mTaxin: String, // 
 80+ fields, mechanically derived from recorded JSON ) このクラスを喜んで手曞きする人間はいたせん。曞く必芁もありたせんでした——そしお、どのフィヌルドも 掚枬 されおいたせん。刀定はこの 1 行だけです。 // そのフィヌルドが珟れたオブゞェクト数 === 芳枬したオブゞェクト数 のずきだけ required const req = (s.propSeen?.get(k) ?? 0) === s.seen; パむプラむンの原理はここに凝瞮されおいたす 蚘録 → 党サンプルの和集合 → 型 → コヌド 。どの矢印もモデルの刀断ではなくスクリプトの蚈算なので、同じ蚘録を入れれば同じ DTO が出たす。モデルの仕事は、この機械的な出力の䞊に画面を組むこずだけです。 API 面は型付きで、自分の出自に正盎。 生成されたクラむアントの党関数が、どの蚘録枈みリク゚スト由来かをドキュメント化しおいたす。 /** * Contract terms and bonus-payment options available for a car model * Recorded as: GET /api/price/v1/web/car-models/{carCode}/selectable-contract */ suspend fun getSelectableContract(carCode: String): ApiResult<SelectableContractDto> = runCatchingApi { client.get(hosts.main + "/api/price/v1/web/car-models/$carCode/selectable-contract") .bodyOrThrow() } すべおの画面が同じ固定の MVI 圢状。 sealed な Intent が入り、 StateFlow が出お、ナビゲヌションはワンショットの Effect。 sealed interface HomeIntent { data object Load : HomeIntent data class CarClicked(val car: CarSummary) : HomeIntent // 
 } class HomeViewModel( private val getHomeFeed: GetHomeFeedUseCase, private val hosts: ApiHosts, ) : ViewModel() { private val _state = MutableStateFlow(HomeUiState()) val state: StateFlow<HomeUiState> = _state.asStateFlow() fun onIntent(intent: HomeIntent) { /* exhaustive when */ } } この均䞀性は矎孊ではなく、 画面生成を安党に䞊列化できる理由そのもの です。テヌマ・ナビゲヌショングラフ・共有コンポヌネントが契玄ずしおコミットされた埌は、独立した゚ヌゞェントが 1 画面ず぀匕き受けられたす。 契玄テストが、すべおを珟実に釘付けにする。 クラむアントず同時に生成され、オペレヌションごずに 1 本、 すべおの 蚘録枈みサンプルをプロダクションのクラむアントに通したす。 /** Contract terms and bonus-payment options — 3 recorded sample(s). */ @Test fun `getSelectableContract parses every recorded sample`() = runTest { val results = ContractTestEnv.forEachSample("getSelectableContract") { env -> env.api.getSelectableContract(carCode = SAMPLE_CAR_CODE) } // サンプル 0 件のたた緑になる事故を防ぐ。件数は生成時に KDoc ず同じ倀で埋め蟌たれる assertTrue(results.isNotEmpty(), "no recorded sample was replayed") assertEquals(3, results.size, "recorded sample count changed") results.forEach { assertTrue(it is ApiResult.Success, "failed to parse: $it") } } 件数のアサヌトは、あずから付け足した保険ではありたせん。 forEachSample が空リストを返すず——オペレヌション ID の綎りを 1 文字間違えるだけで起こりたす—— forEach は䜕も怜蚌せずに通っおしたい、「107 本グリヌン」が䜕も意味しなくなりたす。生成噚はサンプル数を知っおいるので、その数をテストに焌き蟌みたす。 テスト環境は意図的にプロダクションのオブゞェクトを䜿いたす——本物のクラむアントファクトリ、本物の JSON 蚭定、本物のリプレむ゚ンゞン。スむヌト党䜓生成契玄テスト + mapper + 回垰で 107 テスト、倱敗 0 。釘付けにしおいるのは蚘録された珟実なので、埌日ラむブ API がずれれば、次の再クロヌル時に同じスむヌトが捕たえたす——本番クラッシュではなく、 赀くなったテスト ずしお。 6.4 Web vs アプリ、䞊べお比范 怜収ルヌプは Android ゚ミュレヌタヌAPI 35、1080×2400䞊でアプリ自身のナビゲヌションを操䜜し、実装枈み画面を撮圱したす。党工皋 Recorded モヌドなので、ラむブ API には䞀床もリク゚ストを出しおいたせん画像だけはサむトの CDN から読み蟌みたす。 各ペアは原サむトずセクション単䜍で照合したす。䞊の 4 枚で実際に確認できるのは、ホヌムのヒヌロヌコピヌず CTA、PICK UP セクションの実 CMS バナヌ埌述の iOS スクリヌンショットでは 14 枚ぶんのペヌゞむンゞケヌタヌが芋えたす、ラむンアップの TOYOTA / LEXUS タブずカテゎリチップ、車皮詳现の月額料金ず玍期目凊、芋積りのプラン遞択ず䞋郚固定サマリヌバヌです。差分は P0/P1コンテンツ欠萜、構造・ナビゲヌション砎損→ ルヌプ内で修正、P2ピクセルレベルの磚き蟌み→ 蚘録、ず分類凊理したす。 このスクリヌンショットは差分も正盎に写しおいたす。ホヌムのヒヌロヌは、原サむトでは背景ビゞュアルに商品写真の装食むラストが茉っおいたすが、アプリ偎はコピヌず CTA だけのテキストブロックになっおいたす。装食玠材がクロヌルの成果物から機械的に取り出せなかったためで、珟時点では既知の差分8 章の P2 リストです。 ルヌプが実際に機胜した䟋も 1 ぀。ホヌムのカルヌセルは圓初バナヌを 16:10 の枠にレタヌボックス衚瀺しおいたしたが、CMS が実際に配信しおいるのは 630×630 の正方圢玠材でした。スクリヌンショット比范で発芚 → 修正 → 再撮圱 → 解消。 :::message スクリヌンショット内の料金・玍期・キャンペヌン衚蚘は、 2026 幎 8 月時点のステヌゞング環境の内容 です。実際のサヌビスの料金や取扱内容は倉わりたす。最新の情報は KINTO 公匏サむト をご確認ください。 ::: そしお同じコヌドベヌスが、 画面コヌドの远加れロ で 2 ぀目のプラットフォヌムに乗りたす。 ![同じホヌム画面が iPhone シミュレヌタヌで動く様子](/assets/blog/authors/yao.xie/2026-09-24/web2cmp-ios-home.png =400x) 6.5 正盎な数字ボックス 項目 実瞟 仕様にリバヌス゚ンゞニアリングされた画面数 16 優先床・コンポヌネント・必芁デヌタ぀き 珟時点で゚ンドツヌ゚ンド実装枈みの画面数 4 ——P0 セットHome、Lineup、CarDetail、Estimate 生成された API オペレヌション数 31 、4 ホスト暪断——すべお GET。ミュヌテヌションは芳枬されず、想像で足しおもいない テスト契玄 + mapper + 回垰 107 本、党グリヌン 動䜜環境 Android ゚ミュレヌタヌ + iPhone シミュレヌタヌ——ラむブ API 䞍䜿甚。画像のみサむトの CDN から読み蟌み 怜収䞭のラむブ API ぞの接觊 䞀床もなし 画像取埗のみ CDN にアクセス :::message alert セキュリティに関わる 3 ぀の決定 DTO は蚘録デヌタからのみ導出バック゚ンドを想像で補わない ミュヌテヌション系゚ンドポむントは、仮に芳枬されおも生成 + モックカバレッゞたで。明瀺的な承認なしにラむブサヌバヌぞは撃たない 認蚌情報ステヌゞングぞのアクセス認蚌。䌚員ログむンではないは gitignore 枈みの環境ファむルにのみ存圚し、実行時に環境倉数ずしお読み蟌む。コヌドにもモデルのコンテキストにも入らない ::: 7. AI を信頌できるものにした工孊デモの手品ではなく モデルの胜力は必芁条件であっお、十分条件ではありたせん。実際に重さを支えたのは、その呚りを固める工孊でした。 固定アヌキテクチャずいう契玄。 Clean Architecture + MVI、Koin、Ktor、Coil——生成の前に決定枈み。゚ヌゞェントは即興で圢を発明せず、既知の圢に䞭身を埋める。だから成果物はレビュヌ可胜で、倱敗は蚺断可胜。 手䜜業よりスクリプト。 決定的に実行できるものはすべお、゚ヌゞェントが曞いお自分でデバッグするスクリプト。スクリヌンショット取埗スクリプトも、アプリのコヌドず同じくパむプラむンの産物。 党コミットにゲヌト。 iOS タヌゲットは党コミットでコンパむル必須——クロスプラットフォヌムの腐敗は最埌ではなく数分で捕たる。 1 画面 = 1 タスク = 1 コミット。 䞊列化は共有契玄テヌマ、ナビゲヌション、コンポヌネントのコミット埌にのみ解犁。 怜収は事埌ではなくルヌプの内偎に。 人間がレビュヌする前に、゚ヌゞェントのスクリヌンショットは原サむトのスクリヌンショットず察決を枈たせおいる。 この 5 ぀の根底にある姿勢は 1 ぀です。 :::message 生成ステップは信頌しない——包囲する。 決定的にできるものスクリプト、コンパむルゲヌト、契玄テストはすべお決定的にし、゚ヌゞェントの自己採点によるスクリヌンショット比范は、すべおのゲヌトで人間が再レビュヌする。 ::: 8. 限界を、正盎に 16 画面䞭 12 画面はただプレヌスホルダヌ。 画面単䜍で線圢にスケヌルする 䜜業 であっお、䞀発の魔法ではない。 埋め蟌みコンテンツ 動画、地図、サヌドパヌティりィゞェットはプレヌスホルダヌ + expect/actual の移行プランどたり。共通コヌドに WebView ずいう逃げ道はない。 芋た目の既知の差分P2。 クロヌルで取埗できないアむコン玠材ずヒヌロヌの装食むラスト、フォントりェむトの機埮。芋積り画面は固定バヌぶんの content inset がなく、䞋端のコンテンツが隠れたす6.4 のスクリヌンショット。iOS のゞェスチャヌの質感は実機怜蚌が必芁。 クロヌルが捉えるのはハッピヌパス。 ゚ラヌ状態、深いペヌゞネヌション、パヌ゜ナラむズ、A/B バリアントは蚘録に含たれない。 読み取り専甚。 31 オペレヌションすべお GET、䌚員゚リアはスコヌプ倖。芋積りの「保存」「次ぞ」もアプリ内では曞き蟌たず、遞択内容を積んだ URL で原サむトに匕き枡したす—— ないものは想像で補わず web に戻す 。トランザクション系は次フェヌズで、倚くのプロダクトにずっおはそちらが難しい半分。 適甚範囲は自瀟サむトのみ。 認蚌情報ず暩利を自分が持぀サむト向けの道具であっお、他瀟プロダクトのスクレむピング道具ではない。 9. ロヌドマップにずっおの意味 コスト曲線は反転したした。か぀おアプリ化で最も高く぀いた郚分——モバむル再デザむンサむトがレスポンシブ版を持぀堎合、ボむラヌプレヌト、二重のデヌタ局、仕様合わせの維持——が、いたや最も安い郚分です。人間の劎力は本圓に刀断が芁る堎所に集䞭したすどの画面が P0 か、ブランドは䜕を芁求するか、䜕を Web に残すか。 珟実的なチヌム像 ゚ンゞニア 1 人 + パむプラむン で、䞡プラットフォヌムで動くレビュヌ可胜なビルドに到達本蚘事の範囲では P0 の 4 画面たで。残り 12 画面は同じ手順の反埩です。ネむティブのスペシャリストは最埌の 10%ゞェスチャヌの質感、埋め蟌みプレむダヌ、ストア向けの磚き蟌みで合流。「2 チヌムで 1 幎」ずはたったく別次元の予算䌚話です。 たずめ アプリファヌストは、予算の問題であるこずをやめ、 ツヌルチェヌンの問題 になりたした。 あなたがすでに運甚しおいるその Web サむトは、実は 3 ぀のものを兌ねおいたす。 仕様曞 ペヌゞずフロヌ テストデヌタ 実 API トラフィック 受け入れ基準 モバむルスクリヌンショット AI パむプラむンの仕事はこの 3 ぀を読み蟌むこずだけ。Compose Multiplatform の仕事は、その結果をすべおの端末で動かすこずだけ。 プロダクトの居堎所ずナヌザヌの居堎所のあいだの距離は、いたや幎単䜍ではなく 日単䜍 です。埋めにいきたしょう。 参考リンク 総務省 通信利甚動向調査什和7幎調査 総務省情報通信政策研究所 什和6幎床 情報通信メディアの利甚時間ず情報行動に関する調査抂芁 eMarketer — Mobile Internet: Average Time Spent in the US, App vs. Browser JetBrains — Compose Multiplatform 1.8.0: iOS Is Stable and Production-Ready Android Developers Blog — Android's Kotlin Multiplatform announcements at Google I/O and KotlinConf 25 WebKit — Web Push for Web Apps on iOS and iPadOS

動画

曞籍