Windows 11上でAndroidアプリを動かす“Windows Subsystem for Android(WSA)”は便利でしたが、Bluetoothが使えない・アプリを起動していないのにvmmemwsaが大きなメモリを消費する――という悩みが最後まで付いて回りました。本記事は、これら2大テーマを実務視点で深掘りし、現行の最適解(代替手段・設計変更・運用術)をまとめた保存版ガイドです。
結論と要点(先に知りたい人向け)
| 項目 | 現状 | 実務での最適解 |
|---|---|---|
| Bluetooth機能 | WSAはBluetoothハードウェアを扱えず、Androidアプリ側からBLE/Classicともにスキャン・接続不可。 | 物理Android端末でのデバッグ/他社エミュレータ/PC側プロキシ(WindowsアプリでBLE処理→WSAのアプリへネット越し連携)へ設計変更。 |
| WSAの提供状況 | WSAおよびAmazon Appstore on Windowsのサポートは2025年3月5日で終了。 | Windows上のモバイル検証は「実機中心」へ移行。資産は早期に“WSAレス”体制にリフト。 |
| vmmemwsaのメモリ | WSAは起動中、Android VMをバックグラウンド保持しメモリを占有。 | WSA設定の[シャットダウン]で解放。 [サブシステムのリソース]は「必要に応じて」に。 Amazon Appstore等の自動起動を停止。 |
| 長期的対処 | WSA後継は提供されていない。 | Android Studio+実機/クラウドテスト/VM(Android-x86)+USB BTドングル経由など、要件に合わせて再設計。 |
WSAでBluetoothが使えない理由を技術的に理解する
WSAはHyper-Vベースの軽量仮想マシンでAndroid環境を提供します。ネットワークはNAT、ストレージは仮想ディスク、入出力は選択的にホストへ“透過”されます。しかしBluetoothはホストの無線アダプタに直接アクセスする仕組みが提供されていません。AndroidのBluetoothAdapter/BluetoothManagerを呼んでも、実機のようなアダプタは存在しないため、スキャンや接続が成立しません。
典型的な挙動として、Android 12以降で必要な権限(BLUETOOTH_SCAN, BLUETOOTH_CONNECTなど)を宣言・許可しても、アダプタが見つからない・オフ扱い・GATT接続が失敗となります。ログに「Bluetooth is not supported」相当のメッセージが出るケースもあります。
チェック用コード(Kotlin・最小)
// Android 12+ 推奨: BluetoothManager から取得
val manager = getSystemService(BLUETOOTH_SERVICE) as android.bluetooth.BluetoothManager
val adapter = manager.adapter
if (adapter == null || !adapter.isEnabled) {
// WSAではここに到達する可能性が高い
// → 物理端末での動作確認に切り替える
}
WSAの設定UIにもBluetoothのトグルは存在せず、Windows 11側でBluetoothがオンになっていても、WSAに橋渡しされることはありません。Windows 11の新機能(LE Audio、マルチストリーム等)もWSAの制限を解消しません。
「それでも開発・検証したい」ための現実解
方針A:物理Android端末でのUSB/Wi‑Fiデバッグ
品質・再現性・将来性の観点で最優先の選択肢です。Android Studio標準のワークフローであり、Bluetooth周りも実機そのままのAPIで検証できます。
- 端末で「開発者向けオプション」を有効にし、「USBデバッグ」をオン。
- PCにAndroid Platform Tools(adb)を配置し、
adb devicesで認識を確認。 - Wi‑Fiデバッグに切替える場合は
adb tcpip 5555→adb connect 端末のIP:5555。 - Android Studioの「実行」から端末を選択してデプロイ。
画面共有が必要ならscrcpy等を併用すれば、会議やリモートでもスムーズに実演できます。
方針B:他社エミュレータの利用
BlueStacks、LDPlayer、Genymotion等のエミュレータは存在しますが、Bluetooth透過は製品・バージョン・PC構成で挙動が大きく変わり、一般に“確実”とは言えません。導入初期に要件(BLE/Classic、距離・スループット、バックグラウンド要件など)と実機との差異を必ず評価してください。
方針C:Android-x86系をVMで動かす+USB Bluetoothドングルをパススルー
VMware WorkstationなどではUSBデバイスをゲストへ引き渡せます。ホスト側の内蔵Bluetoothではなく、USBのBluetoothドングルを用意してVMにアタッチすれば、環境によってはBLEスキャン・接続が可能になる場合があります。ただし、ドライバ整合性・安定性・プロファイルの差に注意が必要です。量産・商用前提の検証にはやはり実機を推奨します。
方針D:設計変更 ― PC側でBluetoothを処理してWSAアプリへ橋渡し
「どうしてもPC上のUIはAndroidで書きたい」場合は、BluetoothをWindowsアプリ側(WinUI 3 / .NET)で担当し、WSA(Android)とはローカル通信でやり取りします。概念図は次の通りです。
[Android App in WSA] --(WebSocket/HTTP/gRPC over localhost)--> [Windows Service/App]
|
(WinRT API)
|
[Bluetooth LE/Classic Device]
Androidアプリは“Bluetoothクライアント”の代わりにネットワーククライアントになり、Windows側サービスはWindows.Devices.Bluetooth APIでGATT/通知/書き込みを行います。プロトコルはgRPCやWebSocketが扱いやすく、メッセージにデバイスUUID・Characteristic UUID・ペイロードを載せればシンプルに実装できます。
最小プロトタイプ例(C#/.NET, Windows側のWebSocketサーバ)
using System.Net;
using System.Net.WebSockets;
using System.Text;
var http = new HttpListener();
http.Prefixes.Add("http://127.0.0.1:5123/ws/");
http.Start();
while (true)
{
var ctx = await http.GetContextAsync();
if (ctx.Request.IsWebSocketRequest)
{
var ws = (await ctx.AcceptWebSocketAsync(null)).WebSocket;
// ここでメッセージを受け取り、BluetoothLEDevice/GattCharacteristicに転送
var buf = new byte[4096];
var res = await ws.ReceiveAsync(buf, CancellationToken.None);
var msg = Encoding.UTF8.GetString(buf, 0, res.Count);
// TODO: JSONで {device:"xx", service:"...", char:"...", write:"..."} を解釈してBLEへ
await ws.SendAsync(Encoding.UTF8.GetBytes("ok"), WebSocketMessageType.Text, true, CancellationToken.None);
}
else ctx.Response.StatusCode = 400;
}
Android側(Kotlin)の呼び出しイメージ
// OkHttp/WebSocket 等で 127.0.0.1:5123 へ接続(WSAのネットワーク設定により、localhostが使えない場合はホストIPを指定)
val client = OkHttpClient()
val req = Request.Builder().url("http://127.0.0.1:5123/ws/").build()
// ... BLE代替のプロトコルでメッセージ送信
この方式はWSAに依存しないため、将来はWindowsアプリ+実機Androidアプリの二段構えで共存させる設計にもスムーズに移行できます。
vmmemwsaが「アプリ未起動でもメモリを食う」理由
vmmemwsaは、WSAのAndroid仮想マシンをホストするプロセスです。Androidアプリを閉じても、仮想マシン自体が動作中であれば、メモリは確保されたままになります。さらにWindowsのメモリ管理(コミット/ワーキングセット/圧縮/スタンバイ)観点では、タスクマネージャに表示される値が「すぐには減らない」ことも普通に起こります。
また、Amazon Appstore本体や一部のAndroidアプリがバックグラウンドで動作を継続すると、WSAは“必要に応じて復帰/維持”され、結果的にvmmemwsaのメモリが張り付いたままに見えることがあります。
いますぐ効く対処(安全・推奨順)
- WSA設定 → システム → [シャットダウン]
このボタンで仮想マシンを停止すれば、保持していたメモリは解放されます。最も安全かつ確実な方法です。 - [サブシステムのリソース]を「必要に応じて」に
WSA設定の「サブシステムのリソース」を「連続」ではなく「必要に応じて」にしておくと、アイドル時にWSAが停止しやすくなり、常時のメモリ占有を抑えられます。 - 自動起動の抑制
Windows 11のスタートアップアプリでAmazon Appstoreの自動実行をオフ。さらに「設定 → アプリ → インストール済みアプリ → Amazon Appstore → アプリのバックグラウンド実行」も抑制しておくと、WSAが勝手に上がりにくくなります。 - 不要アプリの整理
WSA内のアプリが通知や同期のために起動トリガを生むことがあります。不要なAndroidアプリはアンインストールし、キャッシュ/データは定期的に整理します。
どうしても解放されない場合の最終手段(注意!)
UIで止まらない/固まっている場合に限り、自己責任でプロセスを落とす方法があります。作業中のWSAアプリのデータ破損リスクがあるため、まずは上記の手順を試してください。
# vmmemwsa を強制終了(実行中アプリがある場合はデータ喪失に注意)
Get-Process -Name vmmemwsa -ErrorAction SilentlyContinue | Stop-Process -Force
運用で定期的に止めたいなら、Windowsの「タスク スケジューラ」でユーザーのアイドルやログオフをトリガーに上記スクリプトを実行する設計もあります。ただし、まずはWSAの[シャットダウン]ボタンによる停止を優先してください。
WSA終息後の現実的な移行パス
WSAとAmazon Appstore on Windowsは2025年3月5日でサポート終了となりました。以後のWindows上のAndroid検証は、以下のいずれかのWSAに依存しない手段へ移す必要があります。
- Android Studio+実機:開発者の事実上の標準。BLE/位置情報/センサー類などハードウェア依存機能を正確に検証可能。
- クラウド実機テスト:遠隔で多機種・多OSバージョンを同時検証。Bluetoothなどハード機能は制約がある場合があるため、仕様の確認が必要。
- VM+Android-x86+USB BTドングル:特定シナリオ(スキャン/通知/書き込み)をPC一台で回したい検証向け。安定運用にはノウハウが要る。
- 設計転換(PCがハブ):前述のWindows側プロキシ方式。UIをAndroidで書きつつBTはPCが担う分業アーキテクチャ。
「WSAがなくなると困る」ではなく、“WSAに頼らない前提でアーキテクチャを再設計”するのが将来の保守性・再現性・品質の観点で最善です。
Bluetooth代替アーキテクチャの設計ポイント(実践チェックリスト)
| 論点 | 推奨 | 補足 |
|---|---|---|
| 通信方式 | WebSocket / gRPC(双方向・低オーバーヘッド) | HTTP/RESTでも可。通知(Indicate/Notify)を扱うなら双方向が楽。 |
| メッセージ設計 | Device/Service/Characteristic/Operation/ValueをJSONで定義 | 冪等性・再送・タイムアウト・再接続も含める。 |
| セキュリティ | ローカルループバック限定+オリジン制限 | WSAからホストの127.0.0.1へ到達できない構成ではホストIP直指定。 |
| パフォーマンス | バイナリ(Base64含む)扱いに注意 | Notifyの高頻度化に備え、キュー/バッファリング設計を。 |
| 切替容易性 | 実機直接続と同等のドメインモデル | 将来はアプリから直接BLEに戻せるよう抽象化レイヤを設ける。 |
「vmmemwsa を賢く抑える」運用パターン
日次運用の基本
- 作業の区切りでWSA → [シャットダウン]を押す。
- 「サブシステムのリソース」は「必要に応じて」に固定。常時起動を避ける。
- Amazon Appstoreのバックグラウンド実行を制限し、スタートアップ登録を無効化。
スクリプト化(現場の実例)
チームPCで「昼休み・退勤時に自動的に解放したい」という声は多いです。原則UIで停止ですが、最後の砦としてPowerShellをログオフトリガにする方法が取られることがあります。
# StopWsa.ps1(最終手段)
$proc = Get-Process -Name vmmemwsa -ErrorAction SilentlyContinue
if ($proc) {
# まずは穏当な終了を試みたいところだが、WSAに公式CLIがないため最終的には Kill に頼ることになる
Stop-Process -Id $proc.Id -Force
}
# 例:アイドル15分で実行するタスクを作成(管理者PowerShell)
schtasks /Create /TN "WSA_AutoStop" /TR "powershell -NoProfile -ExecutionPolicy Bypass -File C:\Scripts\StopWsa.ps1" /SC ONIDLE /I 15 /RL HIGHEST /F
運用に組み込む際は、誤作動時のデータ損失リスクをチームで共有し、まずはWSA標準UIによる停止徹底を優先してください。
アンインストールと後片付け(WSA依存を完全になくす)
- アプリ:「設定 → アプリ → インストール済みアプリ」からAmazon AppstoreとWindows Subsystem for Androidをアンインストール。
- 仮想化機能の見直し:WSL2やDocker等を使っていないPCでは、Windowsの機能の有効化または無効化から「Hyper‑V」「Virtual Machine Platform」「Windows Hypervisor Platform」をオフにする選択肢も。ただしVBS/Kernel IsolationやWSL2に影響するため、企業ポリシーと整合を取ること。
- ハイパーバイザー停止(高度):仮想化自体を止めたい場合、管理者コマンドで
bcdedit /set hypervisorlaunchtype off(再起動必要)。将来的に仮想化が必要ならautoに戻します。企業環境では情報システム部門の承認を。
ここまで実施すれば、vmmemwsaに悩まされることはなくなります。以後のAndroid検証は実機・クラウド中心で進めれば、ハード依存機能(BLE、NFC、UWB等)の品質保証も行いやすくなります。
よくある質問(FAQ)
Q. WSAにBluetooth対応が追加される見込みは?
WSAは2025年3月5日をもってサポート終了。公式にBluetooth対応が追加される見込みはありません。今後は設計転換または他手段への移行が前提です。
Q. Windows 11のBluetooth強化(LE Audioなど)は関係する?
ホストOSのBluetooth機能拡張であって、WSAの非対応を埋めるものではありません。WSAのAndroidからホストBTへはアクセスできません。
Q. vmmemwsaの表示メモリが減らないのはバグ?
必ずしもバグではありません。仮想マシンのワーキングセットは即時に縮まないことがあり、Windowsのメモリ圧縮・スタンバイ等の都合で見かけ上残ることがあります。[シャットダウン]実行で実体は解放されます。
Q. 強制終了で問題は起きない?
プロセスKillは最後の手段です。実行中アプリの状態やデータが失われる可能性があるため、まずはUIから停止し、それでもダメなときに限定してください。
Q. 他社エミュレータでBLEが動いた。これで十分?
要件次第です。到達可能距離・接続安定性・スループット・バックグラウンド動作・電力挙動など、実機と差が出るポイントは多く、最終検証は実機が原則です。
実装・検証のためのサンプル手順(手元に残せる“型”)
Androidアプリを実機へ出し、BLEログを確実に取る
- Android Studioでビルドタイプにdebugを用意し、BLEのGATTログを
TimberやLogcatへ詳細出力。 - 権限はAndroid 12+向けに
BLUETOOTH_CONNECT/BLUETOOTH_SCAN/ACCESS_FINE_LOCATIONを状況に応じて要求。 - 再現試験書には距離・姿勢・周辺ノイズ(Wi‑Fi/2.4GHz機器)を明記。安定再現の鍵です。
- BLEは遅延・再送・MTU交渉で挙動が変わります。MTU固定/再交渉時のシーケンスを明示し、相手機器と合意。
Windows側プロキシ方式での最小GATT操作(C#)
// 擬似コード:アドレスor UUIDから接続し、特性にWrite
var device = await BluetoothLEDevice.FromIdAsync("BluetoothLE#DeviceId#...");
var services = await device.GetGattServicesAsync();
var svc = services.Services.First(s => s.Uuid == Guid.Parse("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"));
var chars = await svc.GetCharacteristicsAsync();
var ch = chars.Characteristics.First(c => c.Uuid == Guid.Parse("yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"));
var writer = new DataWriter();
writer.WriteBytes(new byte[]{0x01,0x02});
var status = await ch.WriteValueAsync(writer.DetachBuffer(), GattWriteOption.WriteWithResponse);
// 結果をWSA側アプリへWebSocketで返信
WSAからホストへの到達性
ネットワークモードにより、WSAのAndroidから127.0.0.1へ直に届かない場合があります。その際はホストPCのIPアドレスを使うか、WSAの「高度なネットワーク」相当の設定(提供時期により表記差あり)を調整します。企業ネットワークではファイアウォール/ポリシーも確認しましょう。
トラブルの“原因を切り分ける”ための診断表
| 症状 | 想定原因 | 切り分け手順 | 対処 |
|---|---|---|---|
| WSAでBLEスキャンが0件 | WSAはBT非対応 | 実機で同コードを実行 | 実機検証へ切替 or プロキシ方式 |
| vmmemwsaが常に数GB | WSA常駐・バックグラウンド起動 | Amazon Appstoreの活動/WSAのリソース設定確認 | [シャットダウン]実行・自動起動抑制 |
| 強制終了しても再び膨張 | 自動再起動のトリガが残存 | スタートアップ・バックグラウンド許可・通知を確認 | 不要アプリ整理・許可制限 |
| BLEは動くが切断が頻発 | プロファイル不整合/ノイズ/MTU | 実機・電波環境・MTU値でA/B比較 | 再送/リトライ間隔・MTU交渉の見直し |
WSAに固執しないことが、最短で品質を上げる
WSAはWindowsとAndroidの橋渡し役として大きな役目を果たしましたが、Bluetooth非対応という根本的制約と、vmmemwsaの常駐コストは最後まで解決しませんでした。サポート終了後の今は、開発・検証の主戦場を実機やPCネイティブ実装に切り替え、WSAに引きずられない設計に改めることが、結果的に品質・速度・将来性のすべてで有利です。
まとめると――
- WSAでAndroidのBluetoothは使えない(検出・接続とも不可)。
- vmmemwsaのメモリは仮想マシンを止める([シャットダウン]、自動起動の抑制)ことで解放。
- 今後は実機中心+要件に応じてエミュレータ/VM/プロキシ方式を使い分ける。
この方針であれば、WSAの制限に時間を取られることなく、ユーザーに価値のある機能開発へリソースを集中できます。
付録:運用メモ(現場貼り出し用の短縮版)
- Bluetoothを使うAndroidアプリのWindows検証=実機へ切り替え(最小コストで最大の再現性)。
- WSAメモリ対策:WSA設定→システム→[シャットダウン]/「サブシステムのリソース」は「必要に応じて」/Amazon Appstoreのバックグラウンド/スタートアップ無効化。
- PCプロキシ:WindowsアプリがBLEを担当→WSAアプリはWebSocket/gRPCでやり取り。
- 強制Killは最後の手段。基本はUIで停止。
- WSA依存の撤廃:アンインストール+仮想化機能の棚卸し、必要ならハイパーバイザー停止。

コメント