{"id":8969,"date":"2025-10-10T23:14:38","date_gmt":"2025-10-10T23:14:38","guid":{"rendered":"https:\/\/pokecon.jp\/job\/?p=8969"},"modified":"2025-10-10T23:14:38","modified_gmt":"2025-10-10T23:14:38","slug":"rails-hotwire-native%e3%81%a7%e4%bd%9c%e3%82%8b%e3%83%8d%e3%82%a4%e3%83%86%e3%82%a3%e3%83%96%e3%83%a2%e3%83%90%e3%82%a4%e3%83%ab%e3%82%a2%e3%83%97%e3%83%aa-android%e7%b7%a8%ef%bc%884%ef%bc%89","status":"publish","type":"post","link":"https:\/\/pokecon.jp\/job\/8969\/","title":{"rendered":"Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff084\uff09\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08\u7ffb\u8a33\uff09\uff5cTechRacho by BPS\u682a\u5f0f\u4f1a\u793e"},"content":{"rendered":"\n<\/p>\n<div id=\"js-single-body\" wp_automatic_readability=\"243.17614770459\">\n<h2>Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff084\uff09\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08\u7ffb\u8a33\uff09<\/h2>\n<p><a target=\"_blank\" href=\"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_09_26\/152176\" data-wpel-link=\"internal\" target=\"_self\">\u524d\u56de\u306e\u8a18\u4e8b<\/a>\u3067\u306f\u3001\u30cd\u30a4\u30c6\u30a3\u30d6\u753b\u9762\u306b\u79fb\u52d5\u3057\u3066 Android Views\u307e\u305f\u306fJetpack Compose\u3067\u30ec\u30f3\u30c0\u30ea\u30f3\u30b0\u3059\u308b\u65b9\u6cd5\u306b\u3064\u3044\u3066\u89e3\u8aac\u3057\u307e\u3057\u305f\u3002<\/p>\n<p>\u3057\u304b\u3057\u30cd\u30a4\u30c6\u30a3\u30d6\u753b\u9762\u306b\u306f\u30c8\u30ec\u30fc\u30c9\u30aa\u30d5\u304c\u3042\u308a\u307e\u3059\u3002\u540c\u3058\u30cd\u30a4\u30c6\u30a3\u30d6\u753b\u9762\u3092\u300ciOS\u7528\u300d\u300cAndroid\u300d\u7528\u306b\u305d\u308c\u305e\u308c\u4f5c\u6210\u3059\u308b\u3068\u3001\u8907\u96d1\u306b\u306a\u3063\u3066\u30b3\u30b9\u30c8\u304c\u304b\u3055\u307f\u307e\u3059\u3002<\/p>\n<p>\u3057\u304b\u3057\u3001\u30e2\u30d0\u30a4\u30eb\u30cd\u30a4\u30c6\u30a3\u30d6\u306a\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0\u306e\u6a5f\u80fd\u3092\u6d3b\u7528\u3057\u305f\u3044\u5834\u5408\u3082\u3042\u308a\u307e\u3059\u3002<\/p>\n<p>\u672c\u65e5\u306f\u3001Web\u753b\u9762\u3067\u30cd\u30a4\u30c6\u30a3\u30d6\u306e\u6a5f\u80fd\u3092\u6d3b\u7528\u3059\u308b\u65b9\u6cd5\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n<h3><a target=\"_blank\" id=\"bridge-component\" href=\"#bridge-component\">\ud83d\udd17<\/a> \u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8<\/h3>\n<p><strong><a target=\"_blank\" href=\"https:\/\/native.hotwired.dev\/reference\/bridge-components\" data-wpel-link=\"external\" target=\"_blank\" rel=\"external noopener\" class=\"wpel-icon-right\">\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08bridge component\uff09<span class=\"wpel-icon wpel-image wpel-icon-19\"\/><\/a><\/strong>\u306fStimulus\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u306e\u62e1\u5f35\u3067\u3001\u30cd\u30a4\u30c6\u30a3\u30d6\u30a2\u30d7\u30ea\u306b\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u9001\u4fe1\u3067\u304d\u308b\u3088\u3046\u306b\u3057\u307e\u3059\u3002<\/p>\n<p>\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306f\u4ee5\u4e0b\u306e\u624b\u9806\u3067\u5b9f\u88c5\u3057\u307e\u3059\u3002<\/p>\n<ol>\n<li>\u30cd\u30a4\u30c6\u30a3\u30d6\u30a2\u30d7\u30ea\u306b\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u9001\u53d7\u4fe1\u3067\u304d\u308bJavaScript\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3092\u4f5c\u6210\u3059\u308b<\/li>\n<li>Web\u30a2\u30d7\u30ea\u304b\u3089\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u53d7\u4fe1\u3057\u3066\u8fd4\u4fe1\u3067\u304d\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3092\u4f5c\u6210\u3059\u308b<\/li>\n<li>Android\u30a2\u30d7\u30ea\u306eHotwire\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u30ec\u30b8\u30b9\u30bf\u306b\u30cd\u30a4\u30c6\u30a3\u30d6\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3092\u8ffd\u52a0\u3059\u308b<\/li>\n<\/ol>\n<p>\u30d6\u30ea\u30c3\u30b8\u3067\u91cd\u8981\u306a\u30e1\u30bd\u30c3\u30c9\u306f<a target=\"_blank\" href=\"https:\/\/github.com\/hotwired\/hotwire-native-bridge\/blob\/main\/src\/bridge_component.js#L44\" data-wpel-link=\"external\" target=\"_blank\" rel=\"external noopener\" class=\"wpel-icon-right\"><code>send<\/code><span class=\"wpel-icon wpel-image wpel-icon-19\"\/><\/a>\u30e1\u30bd\u30c3\u30c9\u3067\u3059\u3002\u3053\u306e\u30e1\u30bd\u30c3\u30c9\u306f\u3001\u300c\u30a4\u30d9\u30f3\u30c8\u300d\u300c\u30c7\u30fc\u30bf\u300d\u300c\u30b3\u30fc\u30eb\u30d0\u30c3\u30af\u300d\u3092\u53d7\u3051\u53d6\u308a\u3001\u30cd\u30a4\u30c6\u30a3\u30d6\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u304c\u30e1\u30c3\u30bb\u30fc\u30b8\u306b\u8fd4\u4fe1\u3057\u305f\u3068\u304d\u306b\u5b9f\u884c\u3057\u307e\u3059\u3002<\/p>\n<h3><a target=\"_blank\" id=\"first-component\" href=\"#first-component\">\ud83d\udd17<\/a> \u6700\u521d\u306e\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3092\u4f5c\u6210\u3059\u308b<\/h3>\n<p>\u30d5\u30a9\u30fc\u30e0\u306e\u30e2\u30fc\u30c0\u30eb\u306b\u30cd\u30a4\u30c6\u30a3\u30d6\u306eSubmit\uff08\u9001\u4fe1\uff09\u30dc\u30bf\u30f3\u3092\u8ffd\u52a0\u3059\u308b\u30d5\u30a9\u30fc\u30e0\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3092\u69cb\u7bc9\u3057\u307e\u3057\u3087\u3046\u3002<\/p>\n<p><a target=\"_blank\" href=\"https:\/\/techracho.bpsinc.jp\/wp-content\/uploads\/2025\/10\/01_modal_with_form_component-min.png\" data-wpel-link=\"internal\" target=\"_self\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/techracho.bpsinc.jp\/wp-content\/uploads\/2025\/10\/01_modal_with_form_component-min.png\" alt=\"\" width=\"410\" height=\"887\" class=\"aligncenter size-full wp-image-153898\" srcset=\"https:\/\/techracho.bpsinc.jp\/wp-content\/uploads\/2025\/10\/01_modal_with_form_component-min.png 410w, https:\/\/techracho.bpsinc.jp\/wp-content\/uploads\/2025\/10\/01_modal_with_form_component-min-139x300.png 139w\" sizes=\"auto, (max-width: 410px) 100vw, 410px\"\/><\/a><\/p>\n<p>\u6700\u521d\u306bRails\u30a2\u30d7\u30ea\u5074\u3067\u4f5c\u696d\u3057\u307e\u3059\u3002<\/p>\n<p>\u4ee5\u4e0b\u306e\u30b3\u30de\u30f3\u30c9\u3092\u5b9f\u884c\u3057\u3066\u30d6\u30ea\u30c3\u30b8\u30e9\u30a4\u30d6\u30e9\u30ea\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u307e\u3059\u3002<\/p>\n<pre><code class=\"sh\">.\/bin\/importmap pin @hotwired\/stimulus @hotwired\/hotwire-native-bridge\n<\/code><\/pre>\n<p>\u6b21\u306b\u3001<code>app\/javascript\/controllers\/bridge\/form_controller.js<\/code>\u30d5\u30a1\u30a4\u30eb\u3092\u4f5c\u6210\u3057\u3066\u4ee5\u4e0b\u306e\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3092\u4f5c\u6210\u3057\u307e\u3059\u3002<\/p>\n<pre><code class=\"js\">import { BridgeComponent, BridgeElement } from \"@hotwired\/hotwire-native-bridge\"\n\nexport default class extends BridgeComponent {\n  static component = \"form\"\n  static targets = [ \"submit\" ]\n\n  submitTargetConnected(target) {\n    const submitButton = new BridgeElement(target)\n    const submitTitle = submitButton.title\n\n    this.send(\"connect\", { submitTitle }, () =&gt; {\n      target.click()\n    })\n  }\n}\n<\/code><\/pre>\n<p>\u6700\u5f8c\u306b\u3001<code>todos\/_form.html.erb<\/code>\u30d5\u30a1\u30a4\u30eb\u306b\u3042\u308b\u30d5\u30a9\u30fc\u30e0\u306bStimulus\u7528\u306e\u30de\u30fc\u30af\u30a2\u30c3\u30d7\u3092\u8ffd\u52a0\u3057\u307e\u3059\u3002<\/p>\n<pre><code class=\"diff\">-\n+\n  \n    <div style=\"color: red\">\n      <h2> prohibited this todo from being saved:<\/h2>\n\n      \n    <\/div>\n  \n\n  \n\n  \n\n  <p>\n-   \n+   \n  <\/p>\n\n<\/code><\/pre>\n<p>Rails\u5074\u306e\u4f5c\u696d\u306f\u3053\u308c\u3067\u3059\u3079\u3066\u304a\u3057\u307e\u3044\u3067\u3059\u3002<\/p>\n<h3><a target=\"_blank\" id=\"build-android-component\" href=\"#build-android-component\">\ud83d\udd17<\/a> Android\u306e\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3092\u69cb\u7bc9\u3059\u308b<\/h3>\n<p>\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3067\u306f\u4ee5\u4e0b\u3092\u884c\u3044\u307e\u3059\u3002\u3053\u308c\u306f<a target=\"_blank\" href=\"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_04_03\/148490\" data-wpel-link=\"internal\" target=\"_self\">iOS\u306e\u5834\u5408<\/a>\u3068\u4f3c\u3066\u3044\u307e\u3059\u3002<\/p>\n<ol>\n<li>\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u53d7\u4fe1\u3059\u308b<\/li>\n<li>\u53d7\u4fe1\u3057\u305f\u30e1\u30c3\u30bb\u30fc\u30b8\u306b\u5fdc\u7b54\u3059\u308b<\/li>\n<li>WebView\u3078\u306e\u8fd4\u4fe1\u306bAndroid\u30a2\u30d7\u30ea\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u542b\u3081\u308b<\/li>\n<\/ol>\n<p>\u65b0\u3057\u3044\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3092\u69cb\u7bc9\u3059\u308b\u3068\u304d\u306f\u3001\u53ef\u52d5\u90e8\u5206\u304c\u591a\u6570\u3042\u308b\u53ef\u80fd\u6027\u304c\u3042\u308b\u305f\u3081\u3001\u6bb5\u968e\u7684\u306b\u69cb\u7bc9\u3059\u308b\u306e\u304c\u666e\u901a\u3067\u3059\u3002<\/p>\n<p>\u6700\u521d\u306f\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3092\u63a5\u7d9a\u3057\u307e\u3059\u3002<br \/>\u6b21\u306b\u3001\u6a5f\u80fd\u306e\u69cb\u7bc9\u3092\u6bb5\u968e\u7684\u306b\u958b\u59cb\u3057\u307e\u3059\u3002\u3053\u3053\u3067\u306f\u8a66\u884c\u932f\u8aa4\u304c\u4f55\u5ea6\u3082\u7e70\u308a\u8fd4\u3055\u308c\u307e\u3059\u3002<\/p>\n<p><code>bridge<\/code>\u3068\u3044\u3046\u540d\u524d\u3067\u65b0\u3057\u3044\u30d1\u30c3\u30b1\u30fc\u30b8\u3092\u4f5c\u6210\u3057\u3001\u305d\u3053\u306b<code>FormComponent<\/code>\u3068\u3044\u3046\u30d5\u30a1\u30a4\u30eb\u3092\u4ee5\u4e0b\u306e\u5185\u5bb9\u3067\u4f5c\u6210\u3057\u307e\u3059\u3002<\/p>\n<pre><code class=\"kotlin\">\/\/ app\/src\/main\/java\/bridge\/FormComponent.kt\npackage bridge\n\nimport android.util.Log\nimport dev.hotwire.core.bridge.BridgeComponent\nimport dev.hotwire.core.bridge.BridgeDelegate\nimport dev.hotwire.core.bridge.Message\nimport dev.hotwire.navigation.destinations.HotwireDestination\n\nclass FormComponent(\n  name: String,\n  private val formDelegate: BridgeDelegate<hotwiredestination>\n) : BridgeComponent<hotwiredestination>(name, formDelegate) {\n\n  override fun onReceive(message: Message) {\n    when (message.event) {\n      \"connect\" -&gt; handleConnectEvent(message)\n      else -&gt; Log.w(\"FormComponent\", \"Unknown event for message: $message\")\n    }\n  }\n\n  private fun handleConnectEvent(message: Message) {\n\n    Log.w(\"FormComponent\", \"connected\")\n  }\n}\n<\/hotwiredestination><\/hotwiredestination><\/code><\/pre>\n<p>\u6b21\u306f\u3001<code>HotwireApplication<\/code>\u30d5\u30a1\u30a4\u30eb\u306b\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3092\u767b\u9332\u3057\u307e\u3059\u3002<\/p>\n<pre><code class=\"kotlin\">\/\/ \u4ee5\u4e0b\u306eimport\u3082\u8ffd\u52a0\u304c\u5fc5\u8981\nimport dev.hotwire.navigation.config.registerBridgeComponents\nimport dev.hotwire.core.bridge.BridgeComponentFactory\nimport bridge.FormComponent\n\nHotwire.registerBridgeComponents(\n BridgeComponentFactory(\"form\", ::FormComponent)\n)\n<\/code><\/pre>\n<p>\u30a2\u30d7\u30ea\u3092\u30ea\u30d3\u30eb\u30c8\u3057\u3001\u30a8\u30df\u30e5\u30ec\u30fc\u30bf\u30fc\u3067\u30d5\u30a9\u30fc\u30e0\u30da\u30fc\u30b8\u306b\u79fb\u52d5\u3057\u3066\u30e2\u30fc\u30c0\u30eb\u3092\u8868\u793a\u3057\u307e\u3059\u3002<\/p>\n<p>Android Studio\u306e\u30ed\u30b0\uff08\u5de6\u30c4\u30fc\u30eb\u30d0\u30fc\u306eLogcat\uff09\u3092\u78ba\u8a8d\u3059\u308b\u3068\u3001\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u51fa\u529b\u3055\u308c\u3066\u3044\u308b\u306f\u305a\u3067\u3059\u3002<\/p>\n<p><a target=\"_blank\" href=\"https:\/\/techracho.bpsinc.jp\/wp-content\/uploads\/2025\/10\/02_logs-min.png\" data-wpel-link=\"internal\" target=\"_self\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/techracho.bpsinc.jp\/wp-content\/uploads\/2025\/10\/02_logs-min-1024x264.png\" alt=\"\" width=\"1024\" height=\"264\" class=\"aligncenter size-large wp-image-153899\" srcset=\"https:\/\/techracho.bpsinc.jp\/wp-content\/uploads\/2025\/10\/02_logs-min-1024x264.png 1024w, https:\/\/techracho.bpsinc.jp\/wp-content\/uploads\/2025\/10\/02_logs-min-300x77.png 300w, https:\/\/techracho.bpsinc.jp\/wp-content\/uploads\/2025\/10\/02_logs-min-768x198.png 768w, https:\/\/techracho.bpsinc.jp\/wp-content\/uploads\/2025\/10\/02_logs-min-1536x395.png 1536w, https:\/\/techracho.bpsinc.jp\/wp-content\/uploads\/2025\/10\/02_logs-min.png 1670w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"\/><\/a><\/p>\n<p>\u3053\u3053\u307e\u3067\u69cb\u7bc9\u3057\u305f\u30d5\u30a9\u30fc\u30e0\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306f\u6613\u3057\u3044\u90e8\u5206\u3067\u3059\u3002<\/p>\n<p>\u6b21\u306b\u3001Android\u306e\u30a8\u30b3\u30b7\u30b9\u30c6\u30e0\u306b\u304a\u3051\u308b\u3044\u304f\u3064\u304b\u306e\u7570\u306a\u308b\u5074\u9762\u3092\u7406\u89e3\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n<p>\u307e\u305a\u3001<code>WebBottomSheetFragment<\/code>\u3092\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u7de8\u96c6\u3057\u3066\u3001Hotwire Native\u5099\u3048\u4ed8\u3051\u306e\u4e0b\u90e8\u30b7\u30fc\u30c8\u3092\u4f7f\u3046\u4ee3\u308f\u308a\u306b\u3001\u72ec\u81ea\u306e\u30b7\u30fc\u30c8\u3092\u4f7f\u3046\u3088\u3046\u306b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n<pre><code class=\"kotlin\">\/\/ app\/src\/main\/java\/com\/example\/hotwireexample\/WebBottomSheetFragment.kt\npackage com.example.hotwireexample\n\nimport dev.hotwire.navigation.destinations.HotwireDestinationDeepLink\nimport dev.hotwire.navigation.fragments.HotwireWebBottomSheetFragment\nimport android.view.LayoutInflater\nimport android.view.ViewGroup\nimport android.os.Bundle\n\n@HotwireDestinationDeepLink(uri = \"hotwire:\/\/fragment\/web\/modal\/sheet\")\nclass WebBottomSheetFragment : HotwireWebBottomSheetFragment() {\n  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {\n    return inflater.inflate(R.layout.fragment_web_bottom_sheet, container, false)\n  }\n}\n<\/code><\/pre>\n<p>\u6b21\u306b\u3001<code>res\/layout\/<\/code>\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u4e0b\u3067\u3001<code>fragment_web_bottom_sheet<\/code>\u3092\u4ee5\u4e0b\u306e\u5185\u5bb9\u3067\u4f5c\u6210\u3057\u307e\u3059\u3002<\/p>\n<pre><code class=\"xml\"><?xml version=\"1.0\" encoding=\"utf-8\"????>\n<linearlayout xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\" android:layout_width=\"match_parent\" android:layout_height=\"match_parent\" android:orientation=\"vertical\">\n\n    <com.google.android.material.appbar.appbarlayout android:id=\"@+id\/app_bar\" android:layout_width=\"match_parent\" android:layout_height=\"wrap_content\" android:background=\"@color\/transparent\" android:statelistanimator=\"@null\">\n\n        <com.google.android.material.appbar.materialtoolbar android:id=\"@+id\/toolbar\" android:layout_width=\"match_parent\" android:layout_height=\"wrap_content\" android:background=\"@color\/transparent\">\n\n        <androidx.compose.ui.platform.composeview android:id=\"@+id\/compose_view\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\"\/>\n        <\/com.google.android.material.appbar.materialtoolbar>\n\n    <\/com.google.android.material.appbar.appbarlayout>\n\n    <include layout=\"@layout\/hotwire_view_bottom_sheet\" android:layout_width=\"match_parent\" android:layout_height=\"match_parent\" android:background=\"?android:colorBackground\"\/>\n\n<\/linearlayout>\n<\/code><\/pre>\n<p>\u518d\u3073<code>FormComponent<\/code>\u306b\u623b\u308a\u307e\u3057\u3087\u3046\u3002<br \/>Web\u304b\u3089\u53d7\u4fe1\u3057\u305f\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u89e3\u6790\u53ef\u80fd\u306b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n<pre><code class=\"kotlin\">@Serializable\nclass FormExampleComponent(\n    name: String,\n    private val formDelegate: BridgeDelegate<hotwiredestination>\n) : BridgeComponent<hotwiredestination>(name, formDelegate) {\n\n    ...\n\n    private fun handleConnectEvent(message: Message) {\n        val data = message.data<messagedata>() ?: return\n        Log.w(\"FormComponent\", \"connected\")\n    }\n}\n\n@Serializable\ndata class MessageData(\n    @SerialName(\"submitTitle\") val title: String\n)\n<\/messagedata><\/hotwiredestination><\/hotwiredestination><\/code><\/pre>\n<p>\u3053\u3053\u3067Serializable\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3059\u308b\u3067\u3057\u3087\u3046\u3002\u3053\u308c\u306f\u3001\u6b63\u3057\u3044\u30e9\u30a4\u30d6\u30e9\u30ea\u3092\u69cb\u6210\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u3053\u3068\u3092\u610f\u5473\u3057\u307e\u3059\u3002<\/p>\n<p><code>libs.versions.toml<\/code>\u306b\u4ee5\u4e0b\u3092\u8ffd\u52a0\u3057\u307e\u3059\u3002<\/p>\n<pre><code class=\"toml\">[versions]\n...\nserialization = \"1.5.0\"\n\n[libraries]\n...\nkotlin-serialization-json = { module = \"org.jetbrains.kotlinx:kotlinx-serialization-json\", version.ref = \"serialization\"}\n\n[plugins]\n...\njetbrains-serialization = {id = \"org.jetbrains.kotlin.plugin.serialization\", version.ref = \"kotlin\"}\n<\/code><\/pre>\n<p>\u6b21\u306b\u3001\u30a2\u30d7\u30ea\u306e<code>build.gradle.kts<\/code>\u30d5\u30a1\u30a4\u30eb\u306b\u4ee5\u4e0b\u3092\u8ffd\u52a0\u3057\u307e\u3059\u3002<\/p>\n<pre><code class=\"kotlin\">plugins {\n   ...\n    alias(libs.plugins.jetbrains.serialization)\n\n}\n\nandroid {\n  ....\n}\n\ndependencies {\n.   ...\n    implementation(libs.kotlin.serialization.json)\n\n}\n<\/code><\/pre>\n<p>&#8220;Sync Now&#8221;\u304c\u8868\u793a\u3055\u308c\u305f\u3089\u30af\u30ea\u30c3\u30af\u3057\u3066gradle\u30d5\u30a1\u30a4\u30eb\u3092\u540c\u671f\u3059\u308b\u3053\u3068\u3002<\/p>\n<p>\u3053\u308c\u3067<code>BridgeComponent<\/code>\u306e\u69cb\u7bc9\u306b\u5fc5\u8981\u306a\u3082\u306e\u304c\u3059\u3079\u3066\u63c3\u3063\u305f\u306e\u3067\u3001\u3044\u3088\u3044\u3088<code>FormComponent<\/code>\u306e\u4ed5\u4e0a\u3052\u306b\u304b\u304b\u308a\u307e\u3059\u3002<\/p>\n<h3><a target=\"_blank\" id=\"formcomponent\" href=\"#formcomponent\">\ud83d\udd17<\/a> <code>FormComponent<\/code>\u3092\u4ed5\u4e0a\u3052\u308b<\/h3>\n<p>\u9aa8\u7d44\u307f\u304c\u3067\u304d\u305f\u306e\u3067\u3001\u6700\u521d\u306f\u64cd\u4f5c\u3059\u308bAndroid View\u306b\u3064\u3044\u3066\u30af\u30e9\u30b9\u306b\u4f1d\u3048\u307e\u3057\u3087\u3046\u3002<\/p>\n<pre><code class=\"diff\">class FormComponent(\n    name: String,\n    private val formDelegate: BridgeDelegate<hotwiredestination>\n) : BridgeComponent<hotwiredestination>(name, formDelegate) {\n\n+   private val fragment: Fragment\n+       get() = formDelegate.destination.fragment\n+\n+   private val toolbar: MaterialToolbar?\n+       get() = fragment.view?.findViewById(R.id.toolbar)\n+   private var submitMenuItem: android.view.MenuItem? = null\n  ....\n<\/hotwiredestination><\/hotwiredestination><\/code><\/pre>\n<p>\u3053\u306e<code>handleConnectEvent<\/code>\u95a2\u6570\u3067\u306f\u3001\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u30c7\u30fc\u30bf\u3092\u89e3\u6790\u3057\u3001\u305d\u306e\u30c7\u30fc\u30bf\u3092\u4f7f\u3063\u3066\u30c4\u30fc\u30eb\u30d0\u30fc\u306e\u69cb\u7bc9\u3092\u958b\u59cb\u3057\u307e\u3057\u3087\u3046\u3002<\/p>\n<pre><code class=\"kotlin\">  private fun handleConnectEvent(message: Message) {\n        val data = message.data<messagedata>() ?: return\n        Log.w(\"FormComponent\", \"connected\")\n        showToolbarButton(data)\n    }\n\n  private fun showToolbarButton(data: MessageData) {}\n<\/messagedata><\/code><\/pre>\n<p>\u3053\u3053\u307e\u3067\u6765\u308c\u3070\u3001\u69cb\u7bc9\u304c\u5fc5\u8981\u306a\u30d1\u30fc\u30c4\u306f\u3042\u30682\u3064\u3060\u3051\u3067\u3059\u3002<\/p>\n<pre><code class=\"kotlin\">private fun showToolbarButton(data: MessageData) {\n    val menu = toolbar?.menu ?: return\n\n    \/\/ Find the ComposeView by ID in the fragment's view hierarchy\n    val composeView: ComposeView = fragment.view?.findViewById(R.id.compose_view) ?: return\n\n    \/\/ Set the Compose content in the ComposeView\n    composeView.setContent {\n        SubmitButton(\n            title = data.title,\n            onSubmitClick = {\n                Log.d(\"FormComponent\", \"FormComponent button pressed\")\n                replyTo(\"connect\")\n            }\n        )\n    }\n\n    \/\/ Add the ComposeView as the actionView for the menu item\n    submitMenuItem = menu.add(Menu.NONE, 20, 999, data.title).apply {\n        actionView = composeView\n        setShowAsAction(android.view.MenuItem.SHOW_AS_ACTION_ALWAYS)\n    }\n\n    Log.d(\"FormComponent\", \"FormComponent showToolbarButton with ComposeView from layout\")\n}\n\n@Composable\nfun SubmitButton(title: String, onSubmitClick: () -&gt; Unit) {\n    TextButton(onClick = onSubmitClick) {\n        Text(text = title)\n    }\n}\n<\/code><\/pre>\n<p>\u306a\u304a\u3001<code>20<\/code>\u3068<code>999<\/code>\u3068\u3044\u3046\u6570\u5b57\u3092\u9078\u3093\u3060\u7279\u5225\u306a\u7406\u7531\u306f\u3042\u308a\u307e\u305b\u3093\u3002<\/p>\n<p>\u5b8c\u6210\u3057\u305f\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306f\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<pre><code class=\"kotlin\">\/\/ app\/src\/main\/java\/bridge\/FormComponent.kt\npackage bridge\n\nimport android.util.Log\nimport dev.hotwire.core.bridge.BridgeComponent\nimport dev.hotwire.core.bridge.BridgeDelegate\nimport dev.hotwire.core.bridge.Message\nimport dev.hotwire.navigation.destinations.HotwireDestination\nimport com.google.android.material.appbar.MaterialToolbar\nimport androidx.fragment.app.Fragment\nimport com.example.hotwireexample.R\nimport android.view.Menu\n\nclass FormComponent(\n  name: String,\n  private val formDelegate: BridgeDelegate<hotwiredestination>\n) : BridgeComponent<hotwiredestination>(name, formDelegate) {\n\n  private val fragment: Fragment\n    get() = formDelegate.destination.fragment\n\n  private val toolbar: MaterialToolbar?\n    get() = fragment.view?.findViewById(R.id.toolbar)\n  private var submitMenuItem: android.view.MenuItem? = null\n\n  override fun onReceive(message: Message) {\n    when (message.event) {\n      \"connect\" -&gt; handleConnectEvent(message)\n      else -&gt; Log.w(\"FormComponent\", \"Unknown event for message: $message\")\n    }\n  }\n\n  private fun handleConnectEvent(message: Message) {\n    val data = message.data<messagedata>() ?: return\n    Log.w(\"FormComponent\", \"connected\")\n    showToolbarButton(data)\n  }\n\n  private fun showToolbarButton(data: MessageData) {\n    val menu = toolbar?.menu ?: return\n\n    \/\/ Find the ComposeView by ID in the fragment's view hierarchy\n    val composeView: ComposeView = fragment.view?.findViewById(R.id.compose_view) ?: return\n\n    \/\/ Set the Compose content in the ComposeView\n    composeView.setContent {\n      SubmitButton(\n        title = data.title,\n        onSubmitClick = {\n          Log.d(\"FormComponent\", \"FormComponent button pressed\")\n          replyTo(\"connect\")\n        }\n      )\n    }\n\n    \/\/ Add the ComposeView as the actionView for the menu item\n    submitMenuItem = menu.add(Menu.NONE, 20, 999, data.title).apply {\n      actionView = composeView\n      setShowAsAction(android.view.MenuItem.SHOW_AS_ACTION_ALWAYS)\n    }\n\n    Log.d(\"FormComponent\", \"FormComponent showToolbarButton with ComposeView from layout\")\n  }\n\n  @Composable\n  fun SubmitButton(title: String, onSubmitClick: () -&gt; Unit) {\n    TextButton(onClick = onSubmitClick) {\n      Text(text = title)\n    }\n  }\n}\n<\/messagedata><\/hotwiredestination><\/hotwiredestination><\/code><\/pre>\n<p>\u4ee5\u4e0a\u3067\u304a\u3057\u307e\u3044\u3067\u3059\u3002<\/p>\n<p>\u6b21\u56de\u306e\u8a18\u4e8b\u3067\u306f\u3001iOS\u30b7\u30ea\u30fc\u30ba\u3067\u884c\u3063\u305f\u306e\u3068\u540c\u69d8\u306b\u3001\u3059\u3079\u3066\u3092\u7d44\u307f\u5408\u308f\u305b\u3066\u30ab\u30b9\u30bf\u30e0Trix\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3092\u69cb\u7bc9\u3057\u307e\u3059\u3002<\/p>\n<p>\u3067\u306f\u305d\u308c\u307e\u3067Happy hacking\uff01<\/p>\n<h2>\u95a2\u9023\u8a18\u4e8b<\/h2>\n<blockquote class=\"wp-embedded-content\" data-secret=\"akqqPtLJHo\" wp_automatic_readability=\"0\">\n<p><a target=\"_blank\" href=\"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_09_03\/152174\" data-wpel-link=\"internal\" target=\"_self\">Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff081\uff09\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\uff08\u7ffb\u8a33\uff09<\/a><\/p>\n<\/blockquote>\n<p><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; clip: rect(1px, 1px, 1px, 1px);\" title=\"\u201cRails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff081\uff09\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\uff08\u7ffb\u8a33\uff09\u201d \u2014 TechRacho\" src=\"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_09_03\/152174\/embed#?secret=akqqPtLJHo\" data-secret=\"akqqPtLJHo\" width=\"500\" height=\"282\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe><\/p>\n<blockquote class=\"wp-embedded-content\" data-secret=\"DvGo6ixOsR\" wp_automatic_readability=\"0\">\n<p><a target=\"_blank\" href=\"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_09_19\/152175\" data-wpel-link=\"internal\" target=\"_self\">Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff082\uff09\u30d1\u30b9\u69cb\u6210\uff08\u7ffb\u8a33\uff09<\/a><\/p>\n<\/blockquote>\n<p><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; clip: rect(1px, 1px, 1px, 1px);\" title=\"\u201cRails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff082\uff09\u30d1\u30b9\u69cb\u6210\uff08\u7ffb\u8a33\uff09\u201d \u2014 TechRacho\" src=\"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_09_19\/152175\/embed#?secret=DvGo6ixOsR\" data-secret=\"DvGo6ixOsR\" width=\"500\" height=\"282\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe><\/p>\n<blockquote class=\"wp-embedded-content\" data-secret=\"hvBEPzzVSb\" wp_automatic_readability=\"0\">\n<p><a target=\"_blank\" href=\"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_09_26\/152176\" data-wpel-link=\"internal\" target=\"_self\">Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff083\uff09\u30cd\u30a4\u30c6\u30a3\u30d6\u753b\u9762\uff08\u7ffb\u8a33\uff09<\/a><\/p>\n<\/blockquote>\n<p><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; clip: rect(1px, 1px, 1px, 1px);\" title=\"\u201cRails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff083\uff09\u30cd\u30a4\u30c6\u30a3\u30d6\u753b\u9762\uff08\u7ffb\u8a33\uff09\u201d \u2014 TechRacho\" src=\"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_09_26\/152176\/embed#?secret=hvBEPzzVSb\" data-secret=\"hvBEPzzVSb\" width=\"500\" height=\"282\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe><\/p>\n<p>\n          <\/div>\n\n<br \/><a href=\"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_10_10\/152180\">\u5143\u306e\u8a18\u4e8b\u3092\u78ba\u8a8d\u3059\u308b <\/a><\/p>\n","protected":false},"excerpt":{"rendered":"Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff084\uff09\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08\u7ffb\u8a33\uff09 \u524d\u56de\u306e\u8a18\u4e8b\u3067\u306f\u3001\u30cd\u30a4\u30c6\u30a3\u30d6\u753b\u9762\u306b\u79fb\u52d5\u3057\u3066 Android Views\u307e\u305f\u306fJetpack  [&hellip;]","protected":false},"author":1,"featured_media":8970,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-8969","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-company-tec"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff084\uff09\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08\u7ffb\u8a33\uff09\uff5cTechRacho by BPS\u682a\u5f0f\u4f1a\u793e - \u30dd\u30b1\u30b3\u30f3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_10_10\/152180\" \/>\n<meta property=\"og:locale\" content=\"ja_JP\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff084\uff09\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08\u7ffb\u8a33\uff09\uff5cTechRacho by BPS\u682a\u5f0f\u4f1a\u793e - \u30dd\u30b1\u30b3\u30f3\" \/>\n<meta property=\"og:description\" content=\"Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff084\uff09\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08\u7ffb\u8a33\uff09 \u524d\u56de\u306e\u8a18\u4e8b\u3067\u306f\u3001\u30cd\u30a4\u30c6\u30a3\u30d6\u753b\u9762\u306b\u79fb\u52d5\u3057\u3066 Android Views\u307e\u305f\u306fJetpack [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_10_10\/152180\" \/>\n<meta property=\"og:site_name\" content=\"\u30dd\u30b1\u30b3\u30f3\" \/>\n<meta property=\"article:published_time\" content=\"2025-10-10T23:14:38+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/rails_hotwire_native_mobile_app_android04_eyecatch2-min.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"720\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"info@pokecon.jp\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u57f7\u7b46\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"info@pokecon.jp\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u63a8\u5b9a\u8aad\u307f\u53d6\u308a\u6642\u9593\" \/>\n\t<meta name=\"twitter:data2\" content=\"4\u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/techracho.bpsinc.jp\\\/hachi8833\\\/2025_10_10\\\/152180#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/8969\\\/\"},\"author\":{\"name\":\"info@pokecon.jp\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#\\\/schema\\\/person\\\/16c9f07b1ba984d165d9aee259bda997\"},\"headline\":\"Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff084\uff09\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08\u7ffb\u8a33\uff09\uff5cTechRacho by BPS\u682a\u5f0f\u4f1a\u793e\",\"datePublished\":\"2025-10-10T23:14:38+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/8969\\\/\"},\"wordCount\":64,\"image\":{\"@id\":\"https:\\\/\\\/techracho.bpsinc.jp\\\/hachi8833\\\/2025_10_10\\\/152180#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/10\\\/rails_hotwire_native_mobile_app_android04_eyecatch2-min.png\",\"articleSection\":[\"\u4f01\u696d\u30c6\u30c3\u30af\"],\"inLanguage\":\"ja\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/8969\\\/\",\"url\":\"https:\\\/\\\/techracho.bpsinc.jp\\\/hachi8833\\\/2025_10_10\\\/152180\",\"name\":\"Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff084\uff09\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08\u7ffb\u8a33\uff09\uff5cTechRacho by BPS\u682a\u5f0f\u4f1a\u793e - \u30dd\u30b1\u30b3\u30f3\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/techracho.bpsinc.jp\\\/hachi8833\\\/2025_10_10\\\/152180#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/techracho.bpsinc.jp\\\/hachi8833\\\/2025_10_10\\\/152180#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/10\\\/rails_hotwire_native_mobile_app_android04_eyecatch2-min.png\",\"datePublished\":\"2025-10-10T23:14:38+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#\\\/schema\\\/person\\\/16c9f07b1ba984d165d9aee259bda997\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/techracho.bpsinc.jp\\\/hachi8833\\\/2025_10_10\\\/152180#breadcrumb\"},\"inLanguage\":\"ja\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/techracho.bpsinc.jp\\\/hachi8833\\\/2025_10_10\\\/152180\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"ja\",\"@id\":\"https:\\\/\\\/techracho.bpsinc.jp\\\/hachi8833\\\/2025_10_10\\\/152180#primaryimage\",\"url\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/10\\\/rails_hotwire_native_mobile_app_android04_eyecatch2-min.png\",\"contentUrl\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/10\\\/rails_hotwire_native_mobile_app_android04_eyecatch2-min.png\",\"width\":1200,\"height\":720},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/techracho.bpsinc.jp\\\/hachi8833\\\/2025_10_10\\\/152180#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u30db\u30fc\u30e0\",\"item\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff084\uff09\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08\u7ffb\u8a33\uff09\uff5cTechRacho by BPS\u682a\u5f0f\u4f1a\u793e\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#website\",\"url\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/\",\"name\":\"\u30dd\u30b1\u30b3\u30f3\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ja\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#\\\/schema\\\/person\\\/16c9f07b1ba984d165d9aee259bda997\",\"name\":\"info@pokecon.jp\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ja\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g\",\"caption\":\"info@pokecon.jp\"},\"url\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/author\\\/infopokecon-jp\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff084\uff09\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08\u7ffb\u8a33\uff09\uff5cTechRacho by BPS\u682a\u5f0f\u4f1a\u793e - \u30dd\u30b1\u30b3\u30f3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_10_10\/152180","og_locale":"ja_JP","og_type":"article","og_title":"Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff084\uff09\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08\u7ffb\u8a33\uff09\uff5cTechRacho by BPS\u682a\u5f0f\u4f1a\u793e - \u30dd\u30b1\u30b3\u30f3","og_description":"Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff084\uff09\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08\u7ffb\u8a33\uff09 \u524d\u56de\u306e\u8a18\u4e8b\u3067\u306f\u3001\u30cd\u30a4\u30c6\u30a3\u30d6\u753b\u9762\u306b\u79fb\u52d5\u3057\u3066 Android Views\u307e\u305f\u306fJetpack [&hellip;]","og_url":"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_10_10\/152180","og_site_name":"\u30dd\u30b1\u30b3\u30f3","article_published_time":"2025-10-10T23:14:38+00:00","og_image":[{"width":1200,"height":720,"url":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/rails_hotwire_native_mobile_app_android04_eyecatch2-min.png","type":"image\/png"}],"author":"info@pokecon.jp","twitter_card":"summary_large_image","twitter_misc":{"\u57f7\u7b46\u8005":"info@pokecon.jp","\u63a8\u5b9a\u8aad\u307f\u53d6\u308a\u6642\u9593":"4\u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_10_10\/152180#article","isPartOf":{"@id":"https:\/\/pokecon.jp\/job\/8969\/"},"author":{"name":"info@pokecon.jp","@id":"https:\/\/pokecon.jp\/job\/#\/schema\/person\/16c9f07b1ba984d165d9aee259bda997"},"headline":"Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff084\uff09\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08\u7ffb\u8a33\uff09\uff5cTechRacho by BPS\u682a\u5f0f\u4f1a\u793e","datePublished":"2025-10-10T23:14:38+00:00","mainEntityOfPage":{"@id":"https:\/\/pokecon.jp\/job\/8969\/"},"wordCount":64,"image":{"@id":"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_10_10\/152180#primaryimage"},"thumbnailUrl":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/rails_hotwire_native_mobile_app_android04_eyecatch2-min.png","articleSection":["\u4f01\u696d\u30c6\u30c3\u30af"],"inLanguage":"ja"},{"@type":"WebPage","@id":"https:\/\/pokecon.jp\/job\/8969\/","url":"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_10_10\/152180","name":"Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff084\uff09\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08\u7ffb\u8a33\uff09\uff5cTechRacho by BPS\u682a\u5f0f\u4f1a\u793e - \u30dd\u30b1\u30b3\u30f3","isPartOf":{"@id":"https:\/\/pokecon.jp\/job\/#website"},"primaryImageOfPage":{"@id":"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_10_10\/152180#primaryimage"},"image":{"@id":"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_10_10\/152180#primaryimage"},"thumbnailUrl":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/rails_hotwire_native_mobile_app_android04_eyecatch2-min.png","datePublished":"2025-10-10T23:14:38+00:00","author":{"@id":"https:\/\/pokecon.jp\/job\/#\/schema\/person\/16c9f07b1ba984d165d9aee259bda997"},"breadcrumb":{"@id":"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_10_10\/152180#breadcrumb"},"inLanguage":"ja","potentialAction":[{"@type":"ReadAction","target":["https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_10_10\/152180"]}]},{"@type":"ImageObject","inLanguage":"ja","@id":"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_10_10\/152180#primaryimage","url":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/rails_hotwire_native_mobile_app_android04_eyecatch2-min.png","contentUrl":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/rails_hotwire_native_mobile_app_android04_eyecatch2-min.png","width":1200,"height":720},{"@type":"BreadcrumbList","@id":"https:\/\/techracho.bpsinc.jp\/hachi8833\/2025_10_10\/152180#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u30db\u30fc\u30e0","item":"https:\/\/pokecon.jp\/job\/"},{"@type":"ListItem","position":2,"name":"Rails: Hotwire Native\u3067\u4f5c\u308b\u30cd\u30a4\u30c6\u30a3\u30d6\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea: Android\u7de8\uff084\uff09\u30d6\u30ea\u30c3\u30b8\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\uff08\u7ffb\u8a33\uff09\uff5cTechRacho by BPS\u682a\u5f0f\u4f1a\u793e"}]},{"@type":"WebSite","@id":"https:\/\/pokecon.jp\/job\/#website","url":"https:\/\/pokecon.jp\/job\/","name":"\u30dd\u30b1\u30b3\u30f3","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/pokecon.jp\/job\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ja"},{"@type":"Person","@id":"https:\/\/pokecon.jp\/job\/#\/schema\/person\/16c9f07b1ba984d165d9aee259bda997","name":"info@pokecon.jp","image":{"@type":"ImageObject","inLanguage":"ja","@id":"https:\/\/secure.gravatar.com\/avatar\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g","caption":"info@pokecon.jp"},"url":"https:\/\/pokecon.jp\/job\/author\/infopokecon-jp\/"}]}},"_links":{"self":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts\/8969","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/comments?post=8969"}],"version-history":[{"count":1,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts\/8969\/revisions"}],"predecessor-version":[{"id":8971,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts\/8969\/revisions\/8971"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/media\/8970"}],"wp:attachment":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/media?parent=8969"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/categories?post=8969"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/tags?post=8969"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}