The Android Developer Challenge is back! Submit your idea before December 2.

Android Emulator のネットワークを設定する

エミュレータは、汎用性の高いネットワーク機能を提供します。これを使用して、アプリの複雑なモデリング環境やテスト環境をセットアップできます。以下のセクションでは、エミュレータのネットワークとアーキテクチャの機能について説明します。

ネットワーク アドレス空間

エミュレータの各インスタンスは、仮想ルーターおよびファイアウォール サービスの背後で実行されます。この仮想ルーターおよびファイアウォール サービスによって、各インスタンスは開発マシンのネットワーク インターフェースと設定、そしてインターネットから分離されます。エミュレートしたデバイスでは、開発マシンやネットワーク上のその他のエミュレータ インスタンスは認識されず、イーサネット経由でルーター / ファイアウォールに接続されていることだけが認識されます。

各インスタンスの仮想ルーターは、10.0.2/24 ネットワーク アドレス空間を管理します。ルーターによって管理されるすべてのアドレスは、10.0.2.xx の形式を持ちます(xx は数字)。この空間内のアドレスは、エミュレータ / ルーターによって次のように事前に割り当てられます。

ネットワーク アドレス 説明
10.0.2.1 ルーター / ゲートウェイ アドレス
10.0.2.2 ホスト ループバック インターフェースへの特殊エイリアス(開発マシンの 127.0.0.1 など)
10.0.2.3 1 番目の DNS サーバー
10.0.2.4 / 10.0.2.5 / 10.0.2.6 オプションの 2 番目、3 番目、4 番目の DNS サーバー(存在する場合)
10.0.2.15 エミュレートしたデバイスのネットワーク / イーサネット インターフェース
127.0.0.1 エミュレートしたデバイスのループバック インターフェース

実行中のすべてのエミュレータ インスタンスで同じアドレス割り当てが使用される点に注意してください。つまり、マシン上で 2 つのインスタンスを同時に実行している場合、それぞれに固有のルーターがあり、その背後でそれぞれ 10.0.2.15 の IP アドレスが割り当てられています。2 つのインスタンスはルーターによって分離されており、同じネットワーク上で相互に認識されることはありません。エミュレータ インスタンス間の通信を TCP / UDP で実現する方法については、エミュレータ インスタンスを相互接続するをご覧ください。

また、開発マシンのアドレス 127.0.0.1 は、エミュレータ固有のループバック インターフェースと一致することになります。開発マシンのループバック インターフェース(マシン上の別名 127.0.0.1)で実行されているサービスにアクセスする場合は、代わりに特殊アドレス 10.0.2.2 を使用する必要があります。

最後に、エミュレートしたデバイスの事前割り当てアドレスは、Android Emulator に固有であり、特にルーター/ファイアウォールの背後で NAT 変換されることが多い実際のデバイスでは、大きく異なる可能性が高いので注意してください。

ローカル ネットワークの制限

エミュレータで実行されている Android アプリは、ワークステーションで利用可能なネットワークに接続できます。ただし、アプリはハードウェアに直接接続するのではなく、エミュレータを介して接続し、エミュレータはワークステーション上で通常のアプリのように動作します。これにより、いくつかの制限が生じる可能性があります。

  • エミュレートしたデバイスとの通信は、マシンで実行されているファイアウォール プログラムによってブロックされる場合があります。
  • エミュレートしたデバイスとの通信は、マシンが接続されている別の(物理)ファイアウォール / ルーターによってブロックされる場合があります。

エミュレータの仮想ルーターは、エミュレートしたデバイスに代わってすべてのアウトバウンド TCP / UDP 接続およびメッセージを処理できる必要があります(開発マシンのネットワーク環境で許可されていることが前提)。ホスト オペレーティング システムとネットワークによる制限を除き、ポート番号やポート範囲には初めから設けられている制限はありません。

環境によっては、エミュレータが他のプロトコル(「ping」に使用される ICMP など)をサポートできない場合があります。現在、エミュレータは IGMP(マルチキャスト)をサポートしていません。

ネットワーク リダイレクトを使用する

仮想ルーターの背後にあるエミュレータ インスタンスと通信するには、仮想ルーターでネットワーク リダイレクトを設定する必要があります。設定することで、クライアントは仮想ルーター上の指定されたゲストポートに接続できるようになります。仮想ルーターはゲストポートとエミュレートしたデバイスのホストポート間でトラフィックを転送します。

ネットワーク リダイレクトを設定するには、エミュレータ インスタンスでホストとゲストのポート / アドレスのマッピングを作成します。ネットワーク リダイレクトを設定するには、エミュレータ コンソール コマンドを使用する方法と、adb ツールを使用する方法があります。2 つの方法を以下で説明します。

エミュレータ コンソールを使用してリダイレクトを設定する

各エミュレータ インスタンスには制御コンソールが用意されており、これに接続して各インスタンスに固有のコマンドを発行できます。エミュレータ コンソールで redir コンソール コマンドを必要に応じて使用することで、リダイレクトを設定できます。

最初に、ターゲットのエミュレータ インスタンスのコンソールのポート番号を特定します。たとえば、最初に起動したエミュレータ インスタンスのコンソールのポート番号が 5554 だとします。次に、以下のようにコンソールのポート番号を指定して、ターゲットのエミュレータ インスタンスのコンソールに接続します。

telnet localhost 5554

接続したら、redir コマンドを使用してリダイレクトを操作します。リダイレクトを追加するには、次のようなコマンドを使用します。

add <protocol>:<host-port>:<guest-port>
    

ここで、<protocol>tcp または udp です。<host-port> および <guest-port> は、それぞれ使用しているマシンとエミュレートしたシステム間のマッピングを設定します。

たとえば、次のコマンドは、127.0.0.1:5000 のホスト(開発)マシンへのすべての着信 TCP 接続を処理するリダイレクトを設定し、10.0.2.15:6000 のエミュレートしたシステムに渡します。

redir add tcp:5000:6000

リダイレクトの削除には、redir del コマンドを使用できます。特定のインスタンスのすべてのリダイレクトを一覧表示するには、redir list を使用します。このようなコンソール コマンドの詳細については、エミュレータ コンソールを使用するをご覧ください。

ポート番号はローカル環境によって制限されますので、注意してください。通常、特別な管理者権限がないと 1024 未満のホストポート番号を使用できません。また、マシン上の別のプロセスですでに使用されているホストポートに対してリダイレクトを設定することはできません。設定した場合、redir はその旨を示すエラー メッセージを生成します。

adb を介してリダイレクトを設定する

Android Debug Bridge(adb)ツールは、ポート転送の機能を提供します。この方法を使用することで、上記の方法とは別の方法でネットワーク リダイレクトを設定できます。詳細については、adb ドキュメントのポートの転送をご覧ください。

現在、adb では、adb サーバーを強制終了する以外にリダイレクトを削除する方法がありません。

エミュレータの DNS 設定を構成する

エミュレータは起動時にシステムが現在使用している DNS サーバーのリストを読み取ります。次に、このリストにある最大 4 台のサーバーの IP アドレスを保存し、必要に応じてそれらのサーバーの IP アドレスにエイリアスを設定します(エミュレートしたアドレス 10.0.2.3、10.0.2.4、10.0.2.5、10.0.2.6 を設定)。

Linux および OS X の場合、エミュレータは /etc/resolv.conf ファイルを解析して DNS サーバーのアドレスを取得します。Windows の場合は、GetNetworkParams() API を呼び出してアドレスを取得します。このプロセスでは通常、エミュレータが「hosts」ファイル(Linux / OS X では /etc/hosts、Windows では %WINDOWS%/system32/HOSTS)の内容を無視する点に注意する必要があります。

エミュレータをコマンドラインで起動する場合、-dns-server <serverList> オプションを使用して、使用する DNS サーバーのアドレスを手動で指定することもできます。<serverList> は、サーバー名または IP アドレスのカンマ区切りリストです。エミュレートしたネットワークで DNS 解決の問題(ウェブブラウザ使用時に表示される「不明なホストエラー」メッセージなど)が発生した場合、このオプションが役立つことがあります。

エミュレータでプロキシを使用する

多くの企業ネットワークでは、インターネットへの直接接続は機能しません(ネットワーク管理者によって拒否されます)。ただし、特定のプロキシを経由する場合を除きます。ウェブブラウザおよびその他の企業アプリは、プロキシを使用するように事前に構成されているため、ウェブの閲覧が可能です。エミュレータなどの通常のアプリが機能するためには、プロキシが存在すること、それに接続する必要があることを認識する必要があります。

HTTP の性質により、ウェブサーバーへの直接接続とプロキシ経由の接続では、異なる GET リクエストが生成されます。エミュレータは、プロキシと通信する前に、仮想デバイスからの GET 要求を透過的に書き換えて、動作するようにします。

エミュレータがプロキシ サーバー経由でインターネットにアクセスする必要がある場合は、エミュレータの [Extended controls] 画面からカスタム HTTP プロキシを設定できます。エミュレータを開いた状態で、More アイコン をクリックし、[Settings] と [Proxy] をクリックします。この画面から、固有の HTTP プロキシ設定を定義できます。

または、エミュレータの起動時に -http-proxy <proxy> オプションを使用してコマンドラインからプロキシを設定できます。この場合、プロキシ情報を <proxy> で指定します。形式は次のいずれかになります。

http://<machineName>:<port>

または

http://<username>:<password>@<machineName>:<port>

-http-proxy オプションは、すべての発信 TCP 接続に対して、指定された HTTP / HTTPS プロキシを使用するようにエミュレータに強制します。UDP のリダイレクトは、現在サポートされていません。

または、環境変数 http_proxy<proxy> に使用する値に定義できます。この場合、-http-proxy コマンドで <proxy> の値を指定する必要はありません。エミュレータは起動時に http_proxy 環境変数の値をチェックし、定義されている場合は自動的にその値を使用します。

-debug-proxy オプションを使用することで、プロキシ接続の問題を診断できます。

エミュレータ インスタンスを相互接続する

エミュレータ インスタンスを別のエミュレータ インスタンスと通信できるようにするには、以下に示すように、必須のネットワーク リダイレクトを設定する必要があります。

次のような環境を仮定します。

  • A は開発マシンである
  • B は A で実行される最初のエミュレータ インスタンスである
  • C は 2 番目のエミュレータ インスタンスで、これも A で実行される

B でサーバーを実行し、C がそのサーバーに接続する場合、次のような設定が考えられます。

  1. B のサーバーが 10.0.2.15:<serverPort> をリッスンするよう設定する
  2. B のコンソールで、A:localhost:<localPort> から B:10.0.2.15:<serverPort> へのリダイレクトを設定する
  3. C で、クライアントを 10.0.2.2:<localPort> に接続する

たとえば、HTTP サーバーを実行する場合は、<serverPort> を 80、<localPort> を 8080 に設定します。

  • B は 10.0.2.15:80 でリッスンする
  • B のコンソールで、redir add tcp:8080:80 を発行する
  • C を 10.0.2.2:8080 に接続する

別のエミュレータ インスタンスに音声通話または SMS を送信する

エミュレータは、インスタンス上でシミュレートされた音声通話と SMS メッセージを別のインスタンスに自動的に転送します。音声通話または SMS を送信するには、いずれかのエミュレータから電話アプリまたは SMS アプリをそれぞれ使用します。

シミュレートされた音声通話を別のエミュレータ インスタンスに対して発信するには:

  1. 発信側のエミュレータ インスタンスで電話アプリを起動します。
  2. ダイヤルする番号として、着信側のインスタンスのコンソール ポート番号を入力します。着信側のインスタンスのコンソール ポート番号を確認するには、そのウィンドウ タイトルを確認します。コンソール ポート番号は「Android Emulator (<port>)」で表示されます。
  3. [発信] を押します。着信側のエミュレータ インスタンスに新しい着信が表示されます。

SMS メッセージを別のエミュレータ インスタンスに送信するには、SMS アプリを起動します(利用可能な場合)。着信側のエミュレータ インスタンスのコンソール ポート番号を SMS アドレスとして指定し、メッセージ テキストを入力して、メッセージを送信します。メッセージは着信側のエミュレータ インスタンスに配信されます。

エミュレータ コンソールに接続して、着信音声通話または SMS をシミュレートすることもできます。詳細については、電話のエミュレートおよび SMS のエミュレートをご覧ください。