WebRTCなAndroidネイティブアプリケーションについて

※超軽いノリで行こうと思います。そのほうが筆進むし、ついうっかり要らないこと書けるし。

やぁ。(´・ω・`)ようこそ、バーボンハウスへ。
このページはサービスだから、まず落ちついて見て欲しい。

うん、「またディープなネタ※」なんだ。済まない

謝るつもりもないし、許してもらう謂れもないと思ってる。
そろそろ、WebRTCをテレビ電話以外で活用する話をしてもいいと思うのだけど、
私にとってWebRTCは手段であって目的じゃないんだ。そこのところをわかってほしい。

それではブラウザとJavascriptでお手軽！だったハズのものを、
ネイティブで使うという本末転倒ネタを始めようではないか。

※筆者はWebRTCMeetUpTokyoというイベントでMCUネタを展開しネイティブに突っ込んでいっている

#はじめに
前置きが長くなりました。活用法やメリットの話は置いておくことにして、とりあえず表題について書こうと思います。~~最初はstep by stepでだれでもビルドして動かせるように、なんて考えていたのですが。長くなるのと、ググれば解ることを書いてもなぁ。。。なんて思ったのでノウハウだけをかい摘んで書いていこうと思います。~~
**2014/12/18追記：ググって分かる方法ではビルドできなくなっていたのでちゃんと書くことにしました。申し訳ないです。平に、平にご容赦をっm(__)m**

##WebRTCっネイティブでも使えるんよ
*WebRTCはブラウザで使うやつでしょ？え、ネイティブ？ネイティブって何？*
なんていう話が聞こえてきたので、サクッと話しておくと。
**ブラウザでWebRTCを使いできることはライブラリを用いることでAndroidやiOSのネイティブアプリで実装可能です。**
もちろん、ブラウザとも通信できます。←重要

## あぁ、OpenWebRTCね。知ってる。あれすごいよねー
http://www.openwebrtc.io/
うん。 Ericssonのやってるあれね。あれすごいよね。iOSのBowserは衝撃だったよね。Glassでも動いてるし、RasPiでも動かすつもりみたい。メインになってるのはGStreamerだし、WebRTCワールドが広がるね。今後が楽しみだわー

#って、ちゃうねん
僕は、Googleさんが触ってるWebRTCライブラリの話をしてんねん。Chromeに入ってるのと同じやつやねん。というわけで、更に前置きが長くなったのは、僕が表記をやってるって言うと上記をWebRTC界隈の人に言われたのでした。
みんな知ってるwebrtc.orgの
http://www.webrtc.org/
The Getting Started guide にちゃんと書いてあるんだよ。ほら。iOSまで載ってる。
http://www.webrtc.org/reference/getting-started
**~~このドキュメントの通りやって成功した人がいるのか知らないけどね(・∀・)~~
ちゃんとドキュメント通りにやれば成功しますm(__)m**

とりあえず、僕はダメだったよ。。。**（僕がちゃんとできない子なだけでしたorz）**え、更新されてる気がする＼(^o^)／**←更新を反映しました。**

##AndroidでWebRTC？WebView使えばいいじゃん。
Android Lからはな！むしろロリポップが普及するまで待つという手もある。
https://developer.chrome.com/multidevice/webview/overview

##かい摘んで書くどころか脱線してんじゃん
だって、更新されてたんだもん。
ロシアのサイト
http://devryazantsev.blogspot.ru/p/building-webrtc-trunk-for-andoid-and.html
紹介して、この通りやったらうまくいくぜ。YAHOO!ロシア最高で済ませようと思ったのに。


##~~実は、ここ4ヶ月ほどビルドしてないんだよね。てへっ。~~
~~でも、Androidビルドツールを呼んじゃうビルドスクリプトがOpenJDK 7で動くなんて思えないんだけど動くのかなぁ。AndroidのビルドツールってJDK6依存だぜ？ほら。
https://developer.android.com/sdk/index.html
ちなみに、Ubuntu14.04じゃなくて12.04使う理由も
*Tested on Ubuntu 12.04, Precise Pangolin*
っていうAndroid SDKの一文に由来してるんだ。とりあえず、検証してるからあとで結果書くよ。~~

**ちゃんと検証した結果すべて覆ってました。Ubuntu 14.04のOpenJDK7でOKでした。むしろ12.04のほうが面倒くさいです**

###タイトル変更
*WebRTCなAndroidネイティブアプリケーションをビルドしてみる。*
っていうタイトルで始めたのに全然ビルドし始めないので、
**WebRTCなAndroidネイティブアプリケーションについて**
に変えてみる。

#ビルドのポイント
~~基本的には先ほど書いたRyazantsev S.V.氏のブログ記事
http://devryazantsev.blogspot.ru/p/building-webrtc-trunk-for-andoid-and.html
を参考にビルドしていけば問題なく作成できるはずです。~~**←情報が古いので無理です。。。**
でも、それだけだと色んな人に怒られると思うので何点かポイントを書いていきます
ポイントについてはものによってはiOSでも使えるので参考にどうぞ。

##VM使うのがおすすめ
まぁ、リンク先の記事も書いてますがVM使うのがお勧めです。正常にビルドできて、動いたバージョンのVMイメージを保管しておかないと、*「あの時はビルドできたのに！」*なんていう定番の言い訳を言う困ったことになってしまいます。私はVagrantを使いました。
###VMを使う上で
こちらも記事に書いてありますが、Chromiumに含まれるコードの一部をChromiumのビルドツールでビルドするわけです。CPUとメモリの使用量はお察しください。**メモリ2G,HDD30GB**は必須です。CPUのコアも割り当てられるだけ割り当てておきましょう。ビルドにはそれなりに時間がかかります。事前確認必須です。

##~~Javaバージョンに注意する~~
~~経験上バージョン依存が非常に強いです。どうせやるなら最新版でーなんてやっても失敗するだけなので、ブログ記事と同じバージョンにしましょう。ついでにubuntuも12.04にしておくのがお勧めです。14.04でやった時に失敗した記憶はありますが、よければ誰か試して教えて下さい。
なんだかんだで、ついうっかりJavaのバージョンは変えてしまうので、~~**~~専用のVMを用意することとビルドが通らない時には真っ先にJavaのバージョンを確認することは鉄則です。~~←過去のことです。今はOpenJDK7だけで十分なので、問題になることはないはず**

##trunkはやばい
trunkから取らないとビルドツールが正常に動かないので、ブログ記事通りだとtrunkから取ることになっていますが、trunkからとったソースをビルドしても動かないことがザラにあります。特に日本時間の16時から6時くらいは頻繁に更新されています。trunkから取るときは生活をJST対応に戻しましょう。

##branchesを使う
安定版をビルドしたいなら当然ですがbranchを使いましょう。
見る所によってはbranchが途中までしか表示されませんがこんなにたくさんbrunchがあります。
http://webrtc.googlecode.com/svn/branches/
途中でバージョンが飛んでいるのは、Chromeのそれに一致させたからです。どれをビルドすると良いか解りやすくて良いですよね。

と、いいつつもbranchを取得してビルドするのは若干骨が折れるのと、最新版のbranchは地味に良く切ったあとに差し替えているようなので、
http://src.chromium.org/viewvc/chrome/releases/
から最新版を探しDEPSファイルを見て、webrtcの行を探します。
たとえばchrome 39.0.2132.2の場合は

```
366	   'src/third_party/webrtc':
367	      Var("webrtc") + '/trunk/webrtc@6905',
```

trunkのrevision 6905を使っているとわかりました。しめしめ。。。

##Releaseビルドを使う
`ninja -C out/Debug`
ではなく
`ninja -C out/Release`
でビルドします。パフォーマンスが目に見えて変わるのももちろん、セグメンテーション違反で落ちることも無くなります。もちろんライブラリを利用するのではなく、書き換えるなら話は別ですが。

##OpenSLはDisableがおすすめ
GYP_DEFINESが環境変数に設定された段階で
`export GYP_DEFINES="enable_android_opensl=0 $GYP_DEFINES"`
でも叩いて、OpenSLを切っておきます。でないと、Android端末（特に国産）では音量調整ができないなどの問題が生じます。

#2014/12/18追記：上記を踏まえた上で、ビルド手順を書いていきます。
##ビルド環境について
筆者はUbuntu14.04をVagrant環境で動かしてビルドしました。

使ったのはUbuntu Server 14.04 LTSのvagrantboxです
box自体はubuntuから配布されているデイリービルドのものを使いました。

boxのURLは下記の通り
https://cloud-images.ubuntu.com/vagrant/trusty/trusty-server-cloudimg-amd64-juju-vagrant-disk1.box

Vagrant環境の構築についてはWindowsであれば下記の記事が参考になるかと思います。使っているboxも同じです。
http://blog.kondoyoshiyuki.com/2014/06/12/windows7-vagrant-ubuntu14-04/

initが終わって最初のupをしたら、すぐにhaltをしてアプリケーションメニューからOracle VM VirtualBoxを起動し作成されているVMの設定で**メモリを2G以上にしておきましょう。**コア数も盛っておくといいと思います。常用はしないので、限界まで割り振るのも手です。

割り振ったらsshでアクセスして以降はubuntuでの作業になります。

##定番のおまじないと必須ツールのインストール
よく出てくるコマンドで、とりあえず最新にします。

```
sudo apt-get update
sudo apt-get upgrade
```

gitとsubversion、OpenJDKをインストールし、環境変数にJAVA_HOMEを設定します。

```
sudo apt-get install git subversion openjdk-7-jdk
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
```

OpenJDKのインストールは後から実行するスクリプトにもあるので、ここでは不要かもしれません（未検証）JAVA_HOMEはbashrcあたりに追記してしまえば、起動のたび打たずに済みます。

##実際のビルド
ホームディレクトリからスタートしている前提で話を進めます。
depot toolsをインストールします。といってもGitでcloneして。。。

```
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
```

PATHに追加するだけです。

```
export PATH=`pwd`/depot_tools:"$PATH"
export GYP_DEFINES="OS=android"
```

このPATHとGYP_DEFINESについてもbashrcあたりに追記してもよいと思います。あ、上記のPATHコマンドはgitを実行したのと同じディレクトリで使ってくださいね。pwdコマンド使ってますよ。

ここではお手軽コースと実用コースを用意しました。お手軽のほうがwebrtc.orgに書かれている方法になるので今後も長く使えそうです。ですが、お遊びでなければ実用コースがお勧めです。
###お手軽コース
少ないコマンドで待っているだけで最新版をビルドすることが出来ます。

下記のコマンドを打つだけで必要パッケージのインストールからソースコードのダウンロードまで勝手にやってくれます。しばらくは放置でよいです。

```
fetch webrtc_android
```

ちなみにエラーがでたらとりあえず下記のコマンド。
エラーがでなくても、とりあえず一回打っておくのがオススメです。

```
gclient sync
```

成功したら、srcディレクトリができているので移ります。

```
cd src
```

下記のコマンドで環境変数が設定されます（とはいってもたいした量じゃないですが）**srcディレクトリに移ってから打ちます。先頭のピリオドを忘れずに。ピリオドの後ろにスペースがあるので、ここにも注意！**

```
. build/android/envsetup.sh
```

ここでビルドオプションを設定します。 enable_android_openslはお好みで。国産だとボリュームが効かなくなることも。。。

```
export GYP_DEFINES="build_with_libjingle=1 build_with_chromium=0 libjingle_java=1 enable_android_opensl=0 $GYP_DEFINES"
```
**ちなみに、このGYP_DEFINESを誤った状態でgclient syncなどを使うとエラーでとまります。要注意です。bashrcには書かないほうが良いと思います**

GYP_DEFINESを変えたらお約束です。

```
gclient runhooks
```

最後はビルド、-jオプションの数字はCPUコア数にあわせると良さそうです。4コアな私は4！
**デバッグビルド**

```
ninja -C out/Debug -j4 AppRTCDemo
```

**リリースビルド**

```
ninja -C out/Release -j4 AppRTCDemo
```

###実用？コース。
コマンドの量は多いですが、好みのrevisionがビルドできます。安定版が欲しいときはおすすめです。
今回はrevision 6905をビルドします。他のrevisionを使う場合は6905をそのrevision番号に変えてください。

お手軽コースを検証するときはやらなかったのですが、適当なフォルダを作ってやるのがお勧めです。
失敗したらフォルダごと消してやり直せばよいので。

```
mkdir WebRTCSB
cd WebRTCSB/
```

ここでdepot toolsの設定ファイルを作ります。OSの指定も追記しています。あれ？安定版なのにtrunk？なんで？に対する回答はうえのほうを見てください。

```
gclient config http://webrtc.googlecode.com/svn/trunk
echo "target_os = ['android', 'unix']" >> .gclient
```

ここでソースコードを持ってきます。今回はrevision 6905を取得するので -r 6905とオプションをつけています。最新版ならオプション無しでOKです。時間がかかるので気長に待ちます。

```
gclient sync --nohooks -r 6905
```

終わったら、OSで見に行くレポジトリの設定を変更します。何らかの方法で/etc/apt/sources.listを開き

```
sudo vi /etc/apt/sources.list
```

multiverseなレポジトリを有効化します。今回の場合は下記の二行のコメントアウトを解除します。

```
deb http://archive.ubuntu.com/ubuntu trusty multiverse
deb http://archive.ubuntu.com/ubuntu trusty-updates multiverse
```

そして、下記のコマンドを実行すれば、ビルド時依存関係のあるパッケージをインストールしてくれます。

```
sudo ./trunk/build/install-build-deps-android.sh
```

ここからは生成されているtrunkディレクトリに移り

```
cd trunk
```

お手軽コースと同じく、環境情報の設定スクリプトを実行

```
. build/android/envsetup.sh
```

ここで、もう一回必要なファイルを取得します。revision 6905を取得するのでさきほど同様オプションがついています。もう一つのオプションはnohooksがforceに変わっています。

```
gclient sync --force -r 6905
```

ここからはお手軽コースと同じ流れになります。
GYP_DEFINESにビルドオプションを設定します。

```
export GYP_DEFINES="build_with_libjingle=1 build_with_chromium=0 libjingle_java=1 enable_android_opensl=0 $GYP_DEFINES"
```

そして、GYP_DEFINESを変えた時のおまじないをし

```
gclient runhooks
```

ビルドします。

```
ninja -C out/Release -j4 AppRTCDemo
```

###gclient系のコマンドでエラーが出る場合は
繰り返しになりますがGYP_DEFINESに無効なオプションが設定されている可能性が高いので確認してください。とりあえず、下記のコマンドを叩くのも可です。

```
export GYP_DEFINES="OS=android"
```

そのごはエラーが出たコマンドを叩けば、今度は通るはずです。

#ビルドできたーーー
AppRTCDemo.apkなんていうような（うる覚え）APKが生成されているかと思います。
これはGoogleさんちのWebRTC定番デモ、AppRTCにつながるのでやってみてください。
https://apprtc.appspot.com/
##あれ？jarが動かないよ？
残念out/Releaseに生成されたjarはフェイクだ。。。フェイクとは言いませんが、使えないので
trunk/talk/examples/android
以下に生成されているAppRTCDemoのものを使うのが一番お手軽です。
ちなみに、このディレクトリを丸コピしてeclipseで取り込むとビルド環境要らずでeclipseとADTでビルドができる素敵構成になっていますので、この段階でビルド環境からおさらばできます。

###上記のビルド手順の通り進めているのであれば
AppRTCのapkは

```
cp out/Release/AppRTCDemo-debug.apk /vagrant/
```

AppRTCのプロジェクトは

```
cp -r talk/examples/android /vagrant/
```

でコピーすることでホストPCでvagrant initした時のディレクトリにコピーされていますのでご利用ください。

###ちなみに、Androidなら
trunk/webrtc/examples
以下も面白いので遊んでみてください。

もう、vagrantはいらないのでhaltしてしまってよいですが、2回目以降はenvsetup.shやJAVA_HOME、PATH、GYP_DEFINESなどの環境変数系を設定してninjaコマンドを叩けばOKになります。確認のため、ビルドした時の環境変数をexportコマンドで確認して保存しておくと良いかもしれません。

#ライブラリを使っていく上で
ビルドしたライブラリを使ってアプリを作りたくなると思います。そうすると今度は異常動作や不正終了と戦う日々が始まります。ちょっとポイントを書いておきますが、より良い方法があれば教えて下さい。
##Constraintsは全て有効ではない
魅力的なConstraintsの数々にときめくと思いますが、全て有効なわけではありません。例えばAutoGainControlはiOSの場合、iOS標準のものが自動的に利用されるなどオーバーライドされます。動かないことが正常のもののほうが多いです。

##getStatsは呼ばない
PeerConnectionClientのgetStatsは非常に魅力的な関数です。
chrome://webrtc-internals
を呼んだ時のような素敵な情報を提供してくれます。
ですが、これを呼ぶだけでライブラリは一気に不安定になります。
デバッグで使うのは良いのですが、落ちる時には呼ぶのをやめてみましょう。
リリースアプリケーションで呼ぶのはもちろん、利用するのも薦めません。
なにか、良いお作法があれば教えて下さい。

##音に注意する
WebRTCです。魅力的な映像、音声通信機能を使うでしょう。映像はつながらないことがすぐに解りますが、音はそういうわけには行きません。音量は足りてますか？音量ボタンは効きますか？たりない？音量ボタンが効かない？（ニヤニヤ。

##ライブラリを疑う前にアプリケーションを疑う
セグメンテーション違反を起こしてアプリケーションが落ちることが多々あるかと思います。これまで書いたことを心してビルドしたのであれば、ライブラリ自体は安定版であるはずです。AppRTCDemoを見るだけではわからない、関数を呼ぶ順番や状態変化を待つ処理のお作法があります。それを間違えている可能性が高いです。それを書いていたら終わらなくなるので、ここには書きません。あなたの手にある、そのプログラムがノウハウです。

##IssuesとChangesに目を配る
どうにもならない問題が起こったらとりあえずIssuesを見てみましょう。書いてあるかもしれません。
https://code.google.com/p/webrtc/issues/list
あと、trunkを追っかけるときには、Changesも見るのがお勧めです。いろいろ発見があってこれはこれで面白いです。
https://code.google.com/p/webrtc/source/list

##AppRTCのデモだと1:1の通信しかできないんだけどー
複数人でやるときどうすればいいかはクラス構造の話になるので、ここでは勘弁して下さい。とりあえずAppRTCDemoを改造してどうにかなる世界ではないです。

#まとめ
途中から真面目になってしまいました。思い出したらまた書き足しておきます。工数がかなり浮いたはずです。浮いた分僕にご飯おごってくれてもいいのよ？（笑）なんて、こうやって書いてみたら当たり前のことばかり書いている気もします。でも、当たり前のことをなかなか当たり前にできないんですよね。当たり前にやらないと、なかなかうまくビルドできないのでひたすら時間を使ってしまいます。いい具合に泥沼だったんだろうなぁ。なんて、思ってもらえると嬉しいです。

#ようこそ、WebRTCネイティブアプリケーションの世界へ
質問ベースの情報共有を都内でちょこちょこやっているので、ぜひtwitterなりでお声掛け下さい。一人or一社でなんとかなる世界じゃないです。
**4ヶ月触ってないだけでヒーヒー言いながら記事を訂正することになります。ついでに最新版のAppRTCDemoが派手に変わっていて凍りついたりもしています。（余裕のある人は6905のと比較してみてください）**

###なんて
エラソーに書いてますが、僕も今年新卒でWebRTC歴6ヶ月ですし。こんな大きなライブラリをビルドしたことは今までなかったです。もっといい方法あるよ～とかこんなお作法がーなんてありましたら、是非是非、ご指導ご鞭撻いただけますと幸いです。