Genymotion (旧 AndroVM) を Titanium Mobile で使ってみる

# Genymotion (旧 AndroVM) を Titanium Mobile で使ってみる
Androidエミュレータが爆速で動くと話題の **Genymotion** （旧 **AndroVM** ）。せっかくそんなに速いなら、Titanium Mobile から使えるようにしたい！と思いたち、試行錯誤をした結果なんとか使えるようになったのでメモ。

## Genymotionって？
とっても動作が遅いと評判の Android Emulator を代替するプロダクト **[Genymotion](https://cloud.genymotion.com)** 。

x86アーキテクチャのVM上で、Android Emulator を動かそう！ということ **らしい**。 細かいことは実はよく知らない。ちょっと前まで **[AndroidVM](http://androvm.org/blog/)** という名前だったことは知っている。商用プロダクトになったように読めるんだけど、今のところFreeで使えている。今後はどうなるか不明。

詳しくは[こちら](http://www.genymotion.com)を。

## この記事の前提
自分の使い方は少し特殊かもしれないけど、用途は満たしている。Genymotion を知ってしまったいま、今までの開発にはもう戻れないよ。すごい快適だよ。

+ Mac OS 10.8.4
+ Titanium Mobile SDK (3.1.1) と Andorid SDK は正しくインストールされ使えている
+ Android は 4.1 以降のみをターゲットにして開発
+ Titanium Alloy のみ利用
+ Titanium Stuido は使っていない。テキストエディタ + コマンドライン
+ Studioを使ってないのでブレークポイントなどを使った今どきのデバッグはしない
+ [Vagrant](http://qiita.com/sngmr/items/16fb1f0405108eab5ae3)を使っているので、すでに Host Only Network のアダプタが一つ登録されている

## VirtualBoxのインストール
Macの場合は必要なのでインストールする。手順は[割愛](http://qiita.com/sngmr/items/16fb1f0405108eab5ae3)

## Genymotionのインストール
1. [Genymotion](https://cloud.genymotion.com) にアクセスして、まずはユーザー登録を行う
2. Mac OS X 64 bits用のインストーラー（dmgファイル）をダウンロード＆実行して、`Genymotion.app`と`Genymotion Shell.app`をインストールする
3. `Genymotion.app`を実行
4. 「なにもイメージがないけど登録するかい？」っぽいメッセージが表示される。迷わず「YES!!!」
5. 登録したユーザーIDとパスワードでログイン
6. 使いたい Virtual Device を選択して、ダウンロードとインストールと登録を行う。今回試したのは、「Galaxy Nexus - 4.1.1 - with Google Apps - API 16 - 720 * 1280」
7. Genymotion 上に登録された仮想デバイスを Play する。初回は Android SDK のパスを聞かれるので設定する

## VirtualBoxの設定
自分の環境では、すでに VirtualBox 上の仮想マシンが存在したからかもしれないけど、上記手順までやって Play しても、IPアドレスがほげほげと言われて動かなかった(´・ω・｀)。きっと VirtualBox Host-Only Ethernet Adapter の `vboxnet0` が使用済みだったからだと思う。

1. VirtualBox (Oracle VM Virtual Box Manager)を起動して、VirtualBox自身の設定（各VMの設定では **ない**）を表示する
2. [Network]を表示して[Host-only Networks]を追加する。`vboxnet1`が追加された
3. どうも Genymotion で動くVMは、 **192.168.56.X/24** の Host-only Network を使うっぽい。`vboxnet1`に以下のように設定を行った
	
	**Adapter**
	IPv4 Address：192.168.56.1
	IPv4 Network Mask：255.255.255.0
	
	**DHCP Server**
	Enable Server：チェックを入れる
	Server Address：192.168.56.1
	Lower Address Bound：192.168.56.100
	Upper Address Bound：192.168.56.119

	![](https://qiita-image-store.s3.amazonaws.com/0/9195/264438ba-435c-ac45-2de6-5ca57e47c33d.jpeg)

4. Genymotion によって VirtualBox 上に登録された、Android VM の [Settings]を開き、[Network]の[Adapter1]に、先に追加した`vboxnet1`を指定する。[Attached to]は、[Host-only Adapter]を指定
5. [Adapter2]には、[NAT]を指定した

	![](https://qiita-image-store.s3.amazonaws.com/0/9195/f607aaa5-5170-1987-e98e-f68dccc01083.jpeg)

6. Genymotion に戻り、[Play] で実行できるはず

	![](https://qiita-image-store.s3.amazonaws.com/0/9195/d8b855a8-1ab6-0eb4-36bf-3a1d3acf7bd3.jpeg)

## いまはどんな状態？
無事に Mac 上で動いた Genymotion。確かにサクサク動作する。それで今はどんな状態なんだろう。

`adb devices`を実行すると、Genymotion の VM は `device` と表示される。ただし `adb -d shell`はエラーになり、`adb -e shell`にしないと入れない。つまり Genymotion はエミュレータ扱い。

```bash
$ adb devices
List of devices attached 
192.168.56.100:5555	device

$ adb -d shell
error: device not found
$ adb -e shell
shell@android:/ $ 
```

## コマンドラインから Titanium アプリをインストール
Titanium コマンドラインからAndroid 向けビルドを行なえば、adb コマンドでインストールできるはず。ということでやってみる。この辺りは、Titanium なみなさんに色々と教えてもらった。ありがとうございます。

1. Genymotion で Android の VM が動いていることを確認

1. Titanium プロジェクトのディレクトリへ移動する

	```bash
	$ cd Project-Directory
	```

1. Titanium で Android 向けにビルド。エミュレータへのインストールや実行などは行わないフラグをつける

	```bash
	$ titanium build --platform=android --build-only
	```

1. `build/android/bin/app.apk` にアプリがビルドされている。`-s`でデバイスを指定してインストール

	```bash
	$ adb -s 192.168.56.100:5555 install -r build/android/bin/app.apk
	```
	
1. Genymotion にアプリがインストールされている。実行。サクサク。感激！

1. もちろん、こうやってコマンドをつなげてもOK

	```bash
	$ titanium build --platform=android --build-only && adb -s 192.168.56.100:5555 install -r build/android/bin/app.apk
	```

1. Cleanをしたほうがいいとの情報も有り。僕は不要なんだけど、ちょっと分からない。

	```bash
	$ titanium clean && titanium build --platform=android --build-only && adb -s 192.168.56.100:5555 install -r build/android/bin/app.apk
	```

1. **これで思う存分 Android の開発ができるね！**

## もう一歩前へ
**!!!!ここから先は、Titanium に慣れてない人、オススメできないです!!!!**

ここまでで Titanium 製のアプリを Genymotion へインストールするところまで出来た。ただ自動でアプリを起動しないところが気に入らない。Titanium Mobile SDK を改造して、通常のエミュレータと同じように動くようにしてみる。

### Titanium Mobile SDK の編集

この手順は自分で試行錯誤したというより、ほとんど「[開発系もろもろ](http://gettilab.blogspot.jp/2013/05/titanium-androvm.html)」さんを参考にさせて頂いた。ありがとうございます。

Titanium コマンドが、「オマエはエミュレータだな？」と判断する基準は、`adb devices`コマンドで表示されるデバイスの名前が、「`emulator-`」ではじまっていること。
Genymotionは「`192.168.56.100:5555`」みたいな名前になるので、Titanium コマンドからはエミュレータ扱いされない。

そのため、Titanium Mobile SDK 内部の Python と Node.js スクリプトをイジって、強制的にエミュレータとして認識されるようにした。正直IPベタ書きで気に入らないけど、とりあえず動くからOKにしてる。いい方法があったら是非教えて下さい...。

```python:Titanium/mobilesdk/osx/3.1.1.GA/android/androidsdk.py
		# 300行目付近
		for line in out.splitlines():
			line = line.strip()
			if line.startswith("List of devices"): continue
			elif line.startswith("emulator-"):
				(name, status) = line.split()
				port = int(name[name.index("-")+1:])
				offline = False
				if status == "offline":
					offline = True
				devices.append(Device(name, port, True, offline))
			# ↓↓↓↓ 追加 ここから ↓↓↓↓
			elif line.startswith("192.168.56."):
				(name, status) = line.split()
				port = int(name[name.index(":")+1:])
				offline = False
				if status == "offline":
					offline = True
				devices.append(Device(name, port, True, offline))
			# ↑↑↑↑ 追加 ここまで ↑↑↑↑
			elif "device" in line:
				name = line.split()[0]
				devices.append(Device(name))
```

```javascript:Titanium/mobilesdk/osx/3.1.1.GA/android/_build.js
// 465行目付近
devicesProcess.on('exit', function (code, status) {
	if (results.indexOf('emulator') != -1) {
		logger.info(__('Emulator is running') + '\n');
	// ↓↓↓↓ 追加 ここから ↓↓↓↓
	} else if (results.indexOf('192.168.56.') != -1) {
		logger.info(__('AndroVM Emulator is running') + '\n');
	// ↑↑↑↑ 追加 ここまで ↑↑↑↑
	} else {
		emulatorRunning = false;
		logger.info(__('Emulator process exited successfully') + '\n');
		logcatProcess && logcatProcess.kill('SIGKILL');
		adbProcess && adbProcess.kill('SIGKILL');
		buildProcess && buildProcess.kill('SIGKILL');
		emulatorProcess = buildProcess = logcatProcess = adbProcess = null;
	}
});
```

### 実行

1. Genymotion で Android の VM が動いていることを確認

2. 以下のコマンドを発行

	```
	$ cd Project-Directory
	$ titanium build -p android
	```
	
3. Androidエミュレータが起動してしまうので **素早く終了する** 。終了しないと「エミュレータが2つ以上います」って感じのエラーになる

4. Android の VM 上でアプリが実行される

起動してくる Androidエミュレータ を素早く終了するのは面倒なので、またまた Titanium Mobile SDK を編集する。
ただし以下の修正を行うと、（たぶん） Titanium Studio などから普通の Androidデバッグ をやろうとしても、エミュレータが起動しないと思うので注意。

```javascript:Titanium/mobilesdk/osx/3.1.1.GA/android/_build.js
// 448行目付近

// これをコメントアウト
// emulatorProcess = spawn('python', emulatorCmd, { detached: true, stdio: 'ignore' });

// 動かしたくないからこうする
emulatorProcess = spawn('python', ['--version'], { detached: true, stdio: 'ignore' });
```

以上！！
Code Strong!!