<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Expo on 怠惰技術ブログ</title>
    <link>/tags/expo/</link>
    <description>Recent content in Expo on 怠惰技術ブログ</description>
    <generator>Hugo -- 0.147.7</generator>
    <language>ja</language>
    <lastBuildDate>Mon, 23 Feb 2026 21:30:00 +0900</lastBuildDate>
    <atom:link href="/tags/expo/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>WSL2でExpo &#43; E2Eテスト（MaestroとDetox）を試みて完全に詰んだ話</title>
      <link>/posts/2026-02-23-fxxk-mobile-e2e-test/</link>
      <pubDate>Mon, 23 Feb 2026 21:30:00 +0900</pubDate>
      <guid>/posts/2026-02-23-fxxk-mobile-e2e-test/</guid>
      <description>&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;WSL2環境でExpo（React Native）のE2EテストをMaestroとDetoxで試みたが、どちらもWSL2とWindowsエミュレータの構造的な問題で動かなかった。&lt;/p&gt;
&lt;p&gt;かなり過言ではあるが、あえて感情的になるならば、Mobile開発においてMac以外は人権がない。というかあまりにもMac環境以外がだるすぎる。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;環境&#34;&gt;環境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;OS: Windows + WSL2（Ubuntu）&lt;/li&gt;
&lt;li&gt;Expo SDK 54 / React Native 0.81.5&lt;/li&gt;
&lt;li&gt;New Architecture有効&lt;/li&gt;
&lt;li&gt;Androidエミュレータ: Windows側で動作（Medium Phone API 36）&lt;/li&gt;
&lt;li&gt;ADB: Windows側のものをWSL2から参照&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;maestroを試みる&#34;&gt;Maestroを試みる&lt;/h2&gt;
&lt;h3 id=&#34;インストール&#34;&gt;インストール&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -Ls &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://get.maestro.mobile.dev&amp;#34;&lt;/span&gt; | bash
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;export PATH&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$HOME&lt;span style=&#34;color:#e6db74&#34;&gt;/.maestro/bin:&lt;/span&gt;$PATH&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここで最初の罠。&lt;code&gt;maestro --help&lt;/code&gt;を叩くとAI系の全く別のCLIツールが応答した。同名の別アプリが先にPATHに入っていたため。&lt;code&gt;$HOME/.maestro/bin&lt;/code&gt;をPATHの&lt;strong&gt;先頭&lt;/strong&gt;に置くことで解決。&lt;/p&gt;
&lt;h3 id=&#34;フローの準備&#34;&gt;フローの準備&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# .maestro/add_and_complete_task.yml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;appId&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;com.example.myapp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- &lt;span style=&#34;color:#ae81ff&#34;&gt;launchApp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- &lt;span style=&#34;color:#f92672&#34;&gt;tapOn&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;text&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;追加&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- &lt;span style=&#34;color:#f92672&#34;&gt;inputText&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;テストタスク&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- &lt;span style=&#34;color:#f92672&#34;&gt;tapOn&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;text&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;追加する&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- &lt;span style=&#34;color:#f92672&#34;&gt;assertVisible&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;text&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;NOW&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;実行して即死&#34;&gt;実行して即死&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;You have 0 devices connected, which is not enough to run 1 shards.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;エミュレータはWindows側で動いており、&lt;code&gt;adb devices&lt;/code&gt;には&lt;code&gt;emulator-5554&lt;/code&gt;が見えている。しかしMaestroはWSL2側でデバイスを探すため認識できない。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--udid=emulator-5554&lt;/code&gt;を指定しても：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Device emulator-5554 was requested, but it is not connected.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;maestro start-device --platform=android&lt;/code&gt;を試みると：&lt;/p&gt;</description>
    </item>
    <item>
      <title>AsyncStorageって裏側何やってんの？ - 2.0と3.0の実装の違いを調べてみた</title>
      <link>/posts/2026-02-08-async-storage/</link>
      <pubDate>Sun, 08 Feb 2026 17:50:00 +0900</pubDate>
      <guid>/posts/2026-02-08-async-storage/</guid>
      <description>&lt;p&gt;私は普段React NativeでExpo触ってるので、AsyncStorageはよく使うんだけど、「そういえばAsyncStorageって裏側何やってんだろう？」って疑問が湧いてきたので調べてみることにした。&lt;/p&gt;
&lt;h2 id=&#34;asyncstorageの裏側&#34;&gt;AsyncStorageの裏側&lt;/h2&gt;
&lt;p&gt;AsyncStorageのバージョンによって実装が少し違う。&lt;/p&gt;
&lt;h3 id=&#34;asyncstorage-20の実装&#34;&gt;AsyncStorage 2.0の実装&lt;/h3&gt;
&lt;p&gt;iOS/Androidのみ調査。&lt;/p&gt;
&lt;p&gt;公式ドキュメント: &lt;a href=&#34;https://react-native-async-storage.github.io/2.0/advanced/Where-data-stored/&#34;&gt;Where your data is stored - Async Storage&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&#34;ios-20&#34;&gt;iOS (2.0)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;manifest.json&lt;/code&gt;ファイルに保存される&lt;/li&gt;
&lt;li&gt;JSONファイル形式&lt;/li&gt;
&lt;li&gt;パス: &lt;code&gt;Documents/RCTAsyncLocalStorage_V1/manifest.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;詳細: 1024文字以下のデータは&lt;code&gt;manifest.json&lt;/code&gt;に、それより大きいデータは個別ファイル(MD5ハッシュ名)に保存される&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;android-20&#34;&gt;Android (2.0)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;SQLiteデータベースに保存される&lt;/li&gt;
&lt;li&gt;データベース名: &lt;code&gt;RKStorage&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;パス: &lt;code&gt;/data/data/{package_name}/databases/RKStorage&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;asyncstorage-30-nextの実装&#34;&gt;AsyncStorage 3.0 (next)の実装&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;公式ドキュメント&lt;/strong&gt;: &lt;a href=&#34;https://react-native-async-storage.github.io/3.0-next/&#34;&gt;https://react-native-async-storage.github.io/3.0-next/&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&#34;対応プラットフォーム&#34;&gt;対応プラットフォーム&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Android (SQLite)&lt;/li&gt;
&lt;li&gt;iOS (SQLite) ✨&lt;/li&gt;
&lt;li&gt;macOS (SQLite)&lt;/li&gt;
&lt;li&gt;visionOS (legacy fallback, single database only)&lt;/li&gt;
&lt;li&gt;Web (IndexedDB backend)&lt;/li&gt;
&lt;li&gt;Windows (legacy fallback, single database only)&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;ios-30&#34;&gt;iOS (3.0)&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;SQLiteデータベースに変更された&lt;/li&gt;
&lt;li&gt;Androidと同じ実装に統一&lt;/li&gt;
&lt;li&gt;パフォーマンスと安定性が向上&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;android-30&#34;&gt;Android (3.0)&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;引き続きSQLite&lt;/li&gt;
&lt;li&gt;より洗練された実装&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;3.0からはiOSもAndroidも両方SQLiteになって、実装が統一されるそうだ。&lt;/p&gt;
&lt;h5 id=&#34;互換性&#34;&gt;互換性&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;React Native 0.76以降が必要(iOS/Android)&lt;/li&gt;
&lt;li&gt;Kotlin 2.1.0&lt;/li&gt;
&lt;li&gt;iOS minimum target: 13&lt;/li&gt;
&lt;li&gt;Android minimum SDK: 24&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;なぜiosでmanifestjsonからsqliteに変更したのか&#34;&gt;なぜiOSでmanifest.jsonからSQLiteに変更したのか&lt;/h2&gt;
&lt;p&gt;あくまでも推測ではあるがやってみた。&lt;/p&gt;</description>
    </item>
    <item>
      <title>React NativeのTodoアプリで実装する相対時間ベースのプリセット機能</title>
      <link>/posts/2026-02-08-expo-presets/</link>
      <pubDate>Sun, 08 Feb 2026 10:50:00 +0900</pubDate>
      <guid>/posts/2026-02-08-expo-presets/</guid>
      <description>絶対時間ではなく相対時間（dueHoursOffset）で期限を管理することで、繰り返しタスクを効率化するプリセット機能の実装方法を解説</description>
    </item>
    <item>
      <title>三竦（さんすくみ）要件定義書</title>
      <link>/posts/2026-02-06-sansuku/</link>
      <pubDate>Fri, 06 Feb 2026 07:30:00 +0900</pubDate>
      <guid>/posts/2026-02-06-sansuku/</guid>
      <description>犬猿雉の三すくみを使った追跡型対戦ゲームの要件定義。リアルタイムアクション &#43; 戦略性を両立したシンプルなモバイルゲーム</description>
    </item>
    <item>
      <title>Gemini CLIでExpo Todoアプリを爆速開発した話</title>
      <link>/posts/2026-01-31-gemini-cli-expo/</link>
      <pubDate>Sat, 31 Jan 2026 19:00:00 +0900</pubDate>
      <guid>/posts/2026-01-31-gemini-cli-expo/</guid>
      <description>Gemini CLI を使って Expo の Todo アプリを開発した体験記。GEMINI.md でルールを管理し、段階的に機能を追加していく方法を紹介します。</description>
    </item>
    <item>
      <title>React NativeでTextInputの日本語入力が壊れる問題と解決方法</title>
      <link>/posts/2026-01-31-react-native-input-text-ime-bug/</link>
      <pubDate>Sat, 31 Jan 2026 18:30:00 +0900</pubDate>
      <guid>/posts/2026-01-31-react-native-input-text-ime-bug/</guid>
      <description>React NativeのTextInputで日本語入力時に変換候補が消える問題の原因と、autoComplete/autoCorrectによる解決方法を解説します。</description>
    </item>
  </channel>
</rss>
