初めてのモバイルアプリ
Wails アプリを数分で iOS Simulator または Android Emulator 上で実行する
このガイドでは、標準的な Wails デスクトップアプリを iOS Simulator または Android Emulator 上で実行します。Go コードを変更する必要はありません。すべてのターゲットで同じ main.go をビルドします。
所要時間:15~30 分(大部分は初回実行時のツールチェーンのインストールにかかる時間です)
デスクトッププロジェクトから始める
まだプロジェクトがない場合は、新規作成します:
wails3 init -n mymobileapp
cd mymobileapp
まず、デスクトップアプリが動作することを確認します:
wails3 dev
アプリが開いたら終了し、次に進みます。デスクトップで動作するものはすべてモバイルでも動作します。このガイドでは、main.goにも Go コードにも手を加える必要はありません。
プラットフォームを選択する
要件
-
macOS(iOS のビルドは macOS でのみ行えます)
-
完全版の Xcode — コマンドラインツールだけでは不十分です。App Store からインストールしてから、次を実行します:
bashsudo xcode-select -s /Applications/Xcode.app/Contents/Developer sudo xcodebuild -license accept -
Go 1.25 以降と npm(
wails3 initを実行済みであれば、すでにインストールされています)
確認するには wails3 doctor を実行します。検出された iOS SDK の一覧が表示されます。
Simulator 上で実行する
アプリを起動する
wails3 task ios:run
これだけです。アプリがビルドされ、Simulator がまだ起動していなければ起動し、その上でアプリが起動します。
起動すると、変更を加えていないデスクトップアプリが iOS Simulator 上で動作します。main.goもフロントエンドも同じです:

ログをリアルタイム表示する
別のターミナルで次を実行します:
wails3 task ios:logs:dev
Simulator のログをアプリに絞り込み、リアルタイムで表示します。fmt.Printlnと log.Println の出力がここに表示されます。
WebView を調査する
Safari で 開発 → Simulator → アプリを選択します。コンソール、デバッガー、ネットワークパネルなど、Web インスペクタの全機能を使用できます。
変更を加える
任意のフロントエンドファイル(frontend/src/main.js、index.htmlなど)を編集し、wails3 task ios:runを再実行します。Wails がフロントエンドを再ビルドし、アプリを再起動します。
Go コードを変更した場合も、wails3 task ios:runを再実行します。Go の再コンパイルは増分方式のため、変更されたパッケージだけが再ビルドされます。
Xcode で開く(任意)
wails3 task ios:xcode
これにより、build/ios/が Xcode で開きます。Xcode は、実機へのデプロイ、高度なプロファイリング、プロビジョニングプロファイルの管理に使用できます。Wails はビルドのたびに Xcode プロジェクトを再生成するため、生成されたファイルを直接変更しないでください。
要件
Android SDK、NDK、JDKが必要です。最も簡単な方法は Android Studio を使用することですが、コマンドラインツールも使用できます:
Android コマンドラインツールをインストールする
developer.android.com/studio#command-line-tools-onlyからダウンロードし、~/android-sdk/cmdline-tools/latest/に展開します。
SDK コンポーネントをインストールする
sdkmanager "platform-tools" \
"platforms;android-35" \
"build-tools;35.0.0" \
"ndk;26.3.11579264" \
"emulator" \
"system-images;android-35;google_apis;arm64-v8a"
エミュレーターを作成する
avdmanager create avd \
--name wails \
--package "system-images;android-35;google_apis;arm64-v8a" \
--device pixel_7
環境変数を設定する
~/.zshrcまたは ~/.bashrc に追加します:
export ANDROID_HOME=~/android-sdk
export ANDROID_SDK_ROOT=~/android-sdk
export PATH=$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/cmdline-tools/latest/bin
再読み込みします:source ~/.zshrc
JDK をインストールする
# macOS
brew install openjdk@21
export JAVA_HOME=$(brew --prefix openjdk@21)
# Ubuntu/Debian
sudo apt install openjdk-21-jdk
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
# Windows (scoop)
scoop install openjdk21
必要なものがすべて検出されることを確認するため、wails3 doctorを実行します。
Emulator 上で実行する
アプリを起動する
wails3 task android:run
初回実行時には、次の処理が行われます:
- 実行中のエミュレーターがなければ起動する
- バインディングを生成し、フロントエンドをビルドする
- NDK クロスコンパイラーを使用して Go コードをコンパイルし、
libwails.soを生成する - Gradle でデバッグ APK を組み立てる
- エミュレーターにインストールして起動する
ログをリアルタイム表示する
別のターミナルで次を実行します:
wails3 task android:logs
アプリに絞り込んで adb logcat を実行します。fmt.Println の出力がここに表示されます。
WebView を調査する
Chrome を開き、chrome://inspectに移動します。アプリの WebView が Remote Target の下に表示されます。inspectをクリックして DevTools を開きます。
変更を加える
任意のファイルを編集し、wails3 task android:runを再実行します。Gradle の増分ビルドにより、変更されたコードだけが再コンパイルされます。
実行された処理を理解する
main.goには一切変更が加えられていません。すべての処理は Wails が行いました:
- ビルドシステム — プロジェクト内の
Taskfile.ymlには、プラットフォーム固有のツールチェーンを実行するios:*タスクとandroid:*タスクが含まれています。 - Go のクロスコンパイル — 適切な
GOARCHと sysroot を使用したGOOS=iosまたはGOOS=android。 - ネイティブホスト — コンパイル済みの Go コードを組み込み、WebView をホストする、生成済みの Xcode プロジェクト(iOS)または Gradle プロジェクト(Android)。
- アセットの配信 —
frontend/dist/は Go バイナリに埋め込まれ、同じプロセス内から配信されます。localhost サーバーは不要です。
アプリをモバイル対応にする
アプリはすでに動作しますが、スマートフォンの画面ではデスクトップアプリのように見えます。少し変更するだけで、見栄えは大きく改善します。
レスポンシブ CSS
モバイル画面は幅が狭く、入力方法も異なります。frontend/public/style.css(または同等のファイル)で次のように設定します。
/* Prevent horizontal scrolling */
body {
overflow-x: hidden;
}
/* Touch-friendly tap targets */
button {
min-height: 44px;
min-width: 44px;
}
/* Respect the iOS safe area (notch, home indicator) */
body {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}Go でプラットフォームを検出する
ビルドタグを使用すると、共有コードを煩雑にせずにプラットフォーム固有の動作を追加できます。
iOS 専用コード用にmobile_ios.goを作成します。
//go:build ios
package main
import "github.com/wailsapp/wails/v3/pkg/application"
func platformOptions() application.IOSOptions {
return application.IOSOptions{
DisableBounce: true,
}
}Android 専用コード用にmobile_android.goを作成します。
//go:build android
package main
import "github.com/wailsapp/wails/v3/pkg/application"
func platformOptions() application.AndroidOptions {
return application.AndroidOptions{}
}デスクトップでも共有コードをコンパイルできるように、スタブとしてmobile_desktop.goを作成します。
//go:build !ios && !android
package main
type mobileOptions struct{}
func platformOptions() mobileOptions { return mobileOptions{} }JavaScript でプラットフォームを検出し、モバイル専用 UI を制御する
IOS.*とAndroid.*のランタイムオブジェクトは、それぞれ対応するプラットフォームにのみ存在します。デスクトップで呼び出すと例外がスローされます。Kitchen Sink で使用されている適切なパターンは、プラットフォームを一度だけ検出し、モバイル専用コントロールを完全に非表示にすることです。
// Detect platform from the bridge the host injects into the WebView
const platform = (() => {
if (typeof window.wails?.platform === 'function') return window.wails.platform(); // Android
if (window.webkit?.messageHandlers?.external) return 'ios';
return 'desktop';
})();
const isIOS = platform === 'ios';
const isAndroid = platform === 'android';
const isMobile = isIOS || isAndroid;
// Hide any element marked as mobile-only
document.querySelectorAll('.mobile-only').forEach(el => {
el.style.display = isMobile ? '' : 'none';
});次に、HTML では次のように記述します。
<section class="mobile-only">
<button id="btnHaptic">Haptic feedback</button>
</section>この方法なら、モバイル専用ボタンはデスクトップでは一切レンダリングされず、個々の呼び出しを毎回if (isMobile)チェックで保護する必要もありません。
Go 側では、ビルドタグ付きのスタブと組み合わせ、必要なプラットフォームでのみイベントハンドラーが登録されるようにします。
//go:build !ios && !android
package main
import "github.com/wailsapp/wails/v3/pkg/application"
// No-op on desktop — mobile tabs are hidden in the frontend so these
// events are never emitted.
func registerNativeFeatures(app *application.App) {}//go:build ios
package main
import "github.com/wailsapp/wails/v3/pkg/application"
func registerNativeFeatures(app *application.App) {
app.Event.On("common:haptic", func(e *application.CustomEvent) {
// only compiled and called on iOS
application.IOS.Haptic("medium")
})
// ... other handlers
}これはKitchen Sinkで実際に使用されているパターンです。native_features_stub.go、native_features_ios.go、native_features_android.goを参照してください。
触覚フィードバックを追加する(iOS)
import { IOS } from '@wailsio/runtime';
async function onButtonTap() {
if (isIOS) {
await IOS.Haptics.Impact({ style: 'medium' });
}
// ... rest of your handler
}バイブレーションを追加する(Android)
import { Android } from '@wailsio/runtime';
async function onButtonTap() {
if (isAndroid) {
await Android.Haptics.Vibrate(50); // 50ms
}
}本番向けにビルドする
シミュレーター向けビルド(シミュレーターでのテスト用。署名は不要):
wails3 task ios:package
wails3 task ios:deploy-simulator
実機向けビルド(署名 ID とプロビジョニングプロファイルが必要):
wails3 task ios:package \
IOS_PLATFORM=device \
CODESIGN_IDENTITY="Apple Development: You (TEAMID)" \
PROVISIONING_PROFILE=path/to/profile.mobileprovision
wails3 task ios:deploy-device # installs via xcrun devicectl
配布用 IPA(App Store または TestFlight 用):
wails3 task ios:package:ipa IOS_PLATFORM=device \
CODESIGN_IDENTITY="..." \
PROVISIONING_PROFILE=path/to/distribution.mobileprovision
デバッグ APK(Android のデバッグ用キーストアで署名され、直接インストール可能):
wails3 task android:package
wails3 task android:deploy-emulator
リリース APK(独自のキーストアで署名):
ANDROID_KEYSTORE_FILE=/path/to/release.jks \
ANDROID_KEYSTORE_PASSWORD=yourpassword \
ANDROID_KEY_ALIAS=youralias \
ANDROID_KEY_PASSWORD=yourkeypassword \
wails3 task android:package
ユニバーサル APK(arm64 と x86_64 を 1 つのファイルに収録):
wails3 task android:package:fat
トラブルシューティング
wails3 task ios:runが「no iOS SDKs found」で失敗する
完全版の Xcode をインストールし、選択しておく必要があります。
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
xcode-select -p # should print the Xcode path
wails3 task android:runが「SDK not found」で失敗する
ANDROID_HOMEが設定され、エクスポートされていることを確認します。次のコマンドで検証してください。
echo $ANDROID_HOME
ls $ANDROID_HOME/platform-tools/adb
シミュレーターが起動しない
利用可能なシミュレーターを一覧表示し、いずれかを手動で起動します。
xcrun simctl list devices available
xcrun simctl boot "iPhone 16"
chrome://inspectにターゲットが表示されない
WebView はデバッグモードである必要があります(android:runではデフォルトです)。本番ビルドではなく、デバッグビルドを実行していることを確認してください。また、adb devicesでエミュレーターが接続済みと表示されていることも確認します。
セーフエリアのインセットが適用されない
HTML に viewport メタタグが含まれていることを確認してください。
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">Kitchen Sink を試す
最初のアプリが動作したら、ほかに何ができるかを学ぶには、Kitchen Sink のサンプルを試すのが最も近道です。これは、単一のコードベースから iOS、Android、デスクトップで動作する完全な Wails アプリで、触覚フィードバック、位置情報、生体認証、ローカル通知、セキュアストレージなどを網羅しています。
git clone https://github.com/wailsapp/wails.git
cd wails/v3/examples/mobile
wails3 task ios:run # iOS Simulator
wails3 task android:run # Android Emulator
wails3 task run # Desktop
v3/examples/mobile でソースを参照してください。特に native_features_ios.go ファイルと native_features_android.go ファイルは、プラットフォーム固有の機能をコピー&ペーストで実装する際の出発点として役立ちます。
次のステップ
完全なリファレンス:設定オプション、ネイティブタブ、WKWebView の機能・設定の有効/無効を切り替える項目、実機向けビルド、署名。
完全なリファレンス:設定、トースト、Play Store 向けパッケージング、NDK の詳細。
触覚フィードバック、位置情報、生体認証、通知、セキュアストレージを、実行可能な 1 つのアプリにまとめています。