OSSなリモートスマホサービス（STF）が素敵すぎる

# **STF（Smartphone Test Farm）とは**

![stf_site.png](https://qiita-image-store.s3.amazonaws.com/0/43533/f4411148-3059-6992-50a1-4ad0e1bb7bf8.png)

**STF**（[https://openstf.io](https://openstf.io)）は、CyberAgent社がオープンソースで公開しているオンプレミスにリモートスマホ環境を構築できるサービスです。
STFをインストールしたLinux（またはOSX）マシンにお手持ちのスマホ端末をUSB接続しておくだけで、**同じネットワーク上のPCからブラウザ経由でスマホ端末を操作することができます。**

開発元のCyberAgent社では、社内のSTFサーバに常時**170台以上（！）**の端末が接続されていて、日々の開発で活用しているそうです。

以前の [ネコレジの記事](http://qiita.com/tabbyz/items/f42840504ecc6ff4f827) でも紹介した通り、うちの会社も端末は数多く所有（1,300台以上）しているので、このようなサービスを活用してより効率よく業務を回せていければと思い、今回記事にまとめてみました。


# **STFの特徴**
**対応OS**

* Android 2.3.3〜7.1　※2017/1/25現在
    - root化の必要はなし
    - iOSは非対応

**リモートコントロール機能**

* ブラウザからスマホ/タブレット端末のリモートコントロールが可能
* リアルタイム描画
    - Androidのバージョンにもよるが `30-40FPS` 出る
* マルチタッチサポート
    - Altキーを押しながらドラッグすることで、ピンチ、回転、ズーム操作が可能
* 端末画面の回転
    - 実機に触れなくてもブラウザ上のボタンから画面の回転が可能
* クライアント側のキーボードを使用してのキー入力
    - 日本語入力も問題なく可
* コピー&ペースト操作
* APKファイルのインストール、起動
    - ローカルのAPKファイルをブラウザにドラッグ&ドロップするだけで、簡単にアプリのインストールが可能
    - もちろんGoogle Playストアからインストールすることも可能
* スクリーンショットの取得
* デバイスログの取得
* シェルコマンドの実行
* ファイルエクスプローラ機能で端末内のファイルに直接アクセス

**端末管理機能**

* 端末の貸出し状態の管理（貸出中/貸出し可能）
* 端末情報の取得
    - 電話番号、IMEI、ICCID、Androidバージョン、製品名、その他の多くの属性の取得
    - バッテリー残量と健康状態の取得
* Playストアアカウントの管理
    - アカウントの追加、削除


# **使い方**
## 環境準備
* GitHubの [README.md](https://github.com/openstf/stf/blob/master/README.md) に沿ってSTFをインストールします。
* インストールしたマシンにUSBでスマホ端末を接続し、adbコマンドで端末が認識していることを確認します。
- あらかじめ、端末の **[設定 > 開発者向けオプション > USBデバッグ]** を有効にしておく必要があります。

```bash
# 接続されている端末を確認する
$ adb devices
List of devices attached
0123456789abcdef	device

# もし`no permissions`と出たら、adbサービスを再起動して再度確認する
$ sudo adb kill-server
$ sudo adb start-server
$ adb devices
```

## ログイン
* [http://\<STFサーバーのIPアドレス\>:7100](http://localhost:7100) にアクセスします。
* ログイン画面が表示されますが、単なるモックなので個人が識別できれば適当なユーザー情報で問題ありません。
    - ここでは試しに以下のユーザーでログインします。

```bash
Name  : guest
E-mail: guest@example.com
```

## 端末リスト画面
![stf_device_list.png](https://qiita-image-store.s3.amazonaws.com/0/43533/8b63fd48-5556-305c-ae4d-2dcef11013ed.png)

* 現在接続されている端末が一覧に表示されます。
* ステータスが「貸し出し中」となっている端末は、ほかのユーザーが貸し出し中のため利用できません。
    - ユーザ欄にはログイン時に入力した`Name`が表示されます。
* 「利用する」ボタンをクリックすると、端末のリモート接続が開始されます。


## リモート操作画面
![stf_remote_top.png](https://qiita-image-store.s3.amazonaws.com/0/43533/a5f0fd22-54ad-a4aa-4bc6-5ffe8cd6be30.png)

マウスとキーボードを使用して、ブラウザ上からリモート端末を操作できます。
実際の使用感としては、ネットワーク環境さえ整っていれば**レスポンスはとても良いので快適そのもの。**十分、実用に耐えうる使い勝手です。

リモートだからといって操作する上でとくに制約もなく、**タップやスワイプはもちろんのこと、ピンチや回転なども問題なく可能**です。（ドラッグ中にAltキー押下）
ただ、「スマホのタップ＝マウスクリック」ということもあり、慣れないうちは長時間操作していると人差し指がつりそうになりますが・・・。

もし、どうしてもマウスでの操作に馴染めないという場合には、STFのクライアントはスマホブラウザもサポートしているので、**例えばiPhoneのSafariからSTF経由でAndroid端末を操作するなんてことも可能**です。（素敵✨）

また地味に便利な点として、**キー入力する際にクライアントPCのキーボードが使用できる**ので、長文を打つのがとてもラクです。
さらに、クライアントと端末でクリップボードを共有できるので、クライアントPCでコピーした文字列をスマホ端末でペーストすることも可能です。

### ツールバー
![stf_remote_toolbar.png](https://qiita-image-store.s3.amazonaws.com/0/43533/eabd8c43-ad5d-a09d-bcb8-e4fabe1ce89d.png)

**「端末切り替え」ボタン**
複数の端末に接続している場合は、このボタンから操作する端末を切り替えることができます。

**「画面向き変更」ボタン**
画面の向きを回転します。

**「画面の表示/非表示切り替え」ボタン**
画面の描画を一時的に非表示にします。

**「リモート接続切断」ボタン**
利用し終わったらこのボタンを押して接続を切断します。
（ひとつの端末を複数人で同時に使用することはできないため、小まめに切断するように心がけましょう）
ただし、接続したまましばらく操作せずに放置（30分程度？）していると、自動的にタイムアウトで切断されるようです。


## [ダッシュボード] タブ
### ブラウジング
![stf_dashboard_browsing.png](https://qiita-image-store.s3.amazonaws.com/0/43533/81089c24-0184-f0f0-998d-c1158f51b057.png)

URLを入力して「開く」ボタンを押下すると、ブラウザが自動起動し簡単に任意のサイトにアクセスできます。

### アプリアップロード
![stf_dashboard_upload.png](https://qiita-image-store.s3.amazonaws.com/0/43533/1f006bff-8177-4a03-e951-f4a3667d472b.png)

APKファイルをドロップすると、端末上にアプリがインストールされます。
※アンインストールは、端末の画面上から通常の手順で行います。

### アプリ
![stf_dashboard_apps.png](https://qiita-image-store.s3.amazonaws.com/0/43533/76001496-eb4d-b8cc-4780-fd549cde50ed.png)

よく使用するアプリのショートカットです。
例えば「設定」ボタンを押下すれば、ワンタッチで端末の設定アプリが起動します。

### クリップボード
![stf_dashboard_clipboard.png](https://qiita-image-store.s3.amazonaws.com/0/43533/df589065-1dad-c18a-304f-80d76bc3bc1c.png)

端末のクリップボードの内容を取得します。

### シェル
![stf_dashboard_shell.png](https://qiita-image-store.s3.amazonaws.com/0/43533/be9d3c19-9b6d-14e6-e184-9c4104252625.png)

端末上でシェルコマンドを実行します。

### リモードデバッグ
![stf_dashboard_debug.png](https://qiita-image-store.s3.amazonaws.com/0/43533/27137014-857e-04b2-1006-d8784eddca73.png)

表示されているadbコマンドをクライアントPCのコマンドライン上で実行すると、
さも、クライアントPCに端末が直接接続されているかのように振る舞います。
IDEでデバッグする際に便利です。


## [キャプチャ] タブ
![stf_capture.png](https://qiita-image-store.s3.amazonaws.com/0/43533/4d795692-df7f-b947-73a0-501e1b42334d.png)

画面のスクリーンショットを取得します。
ブラウザの「名前を付けて画像を保存」で保存も可能です。

## [自動化] タブ
### Storeカウント
![stf_automation_account.png](https://qiita-image-store.s3.amazonaws.com/0/43533/d7d13f3b-c0c1-ccf8-595a-748545a29895.png)

端末で使用するストアアカウントを管理します。

### 実機設定
![stf_automation_settings.png](https://qiita-image-store.s3.amazonaws.com/0/43533/dc004c6a-f940-b180-a911-457146d1b51c.png)



## [高度機能] タブ
### 高度な入力
![stf_advanced_input.png](https://qiita-image-store.s3.amazonaws.com/0/43533/e56d0cbb-5535-1fe6-8e42-42c8cb9ea2fc.png)


### ポートフォワーディング
![stf_advanced_pfwd.png](https://qiita-image-store.s3.amazonaws.com/0/43533/060d1abb-d19d-9fef-1dd5-56677e302d3e.png)


### メンテナンス
![stf_advanced_maintenance.png](https://qiita-image-store.s3.amazonaws.com/0/43533/24bc9392-b961-ebff-ef8d-73ac4df6ec7f.png)

再起動後は自動で再認識します。


## [エクスプローラー] タブ
![stf_explore.png](https://qiita-image-store.s3.amazonaws.com/0/43533/4f235846-efb6-9a02-6f37-bee4b4d231ed.png)

端末内のファイルに直接アクセスできます。


## [情報] タブ
![stf_info1.png](https://qiita-image-store.s3.amazonaws.com/0/43533/4c6552a5-63e2-e654-230d-bdcab8ab48c9.png)
![stf_info2.png](https://qiita-image-store.s3.amazonaws.com/0/43533/69fae5d1-d92d-007e-5847-a43ce77ec9fb.png)

※画像ではシリアル番号とIMEIはマスクしていますが、問題なく取得できます。

## [ログ] タブ
![stf_log.png](https://qiita-image-store.s3.amazonaws.com/0/43533/73e2150a-1afe-49c2-a563-cf7606479135.png)

リアルタイムにデバイスログを取得することができます。


# FAQ
### Q. iOSには対応してないの？
**A. 現状は対応していません。**
一応 [Issue](https://github.com/openstf/stf/issues/64) は上がっているので、気長に待ちましょう。

### Q. 実機上で発生するバグはSTF経由でも再現するの？
**A. はい、します。**
STFの仕組み的には「リアルタイムに端末のスクリーンショットを取得 → ブラウザ上で描画」しているだけなので（not エミュレート）、基本的にSTFは100%実機と同じ表示になるそうです。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/leader22">@leader22</a> 基本的にはSTFは100%実機と同じ表示です。変なCSSでGPUまわりのアレが見えます。<a href="https://twitter.com/hashtag/caos2015?src=hash">#caos2015</a></p>&mdash; STF (@open_stf) <a href="https://twitter.com/open_stf/status/619142264317579265">2015年7月9日</a></blockquote>

### Q. 音声の再生はできる？
**A. 再生してもクライアント側でその音声を取得することはできません。**
ゲームアプリなどでは結構大きな制約なので対応されると嬉しいのですが、どうやら音声を取得するには端末のroot化が必要なようで、別の手段を検討しているようです。

### Q. カメラは利用できる？
**A. できますが、リモートという性質上実機に直接触れることができないため、カメラを用いたアプリの検証には適しません。**
ただ、カメラの起動やシャッターを切ること自体は問題なく可能です。


# 最後に
このSTFがリリースされたのは2015年7月と、今から1年半以上も前のことなのですが、実はリリース直後に開発者のお2人（SimoさんとGuntherさん）から直接お話を伺う機会を頂くことができました。
（仕事で付き合いのある方を通じて「お会いしたい！」とメールしたところ、快く応じてくれたのを今でも覚えています）

せっかくなので、最後にその時の話を少し。

---
STFのプロジェクト自体は2年前（※当時）からスタートしていて、基本的にSimoさんとGuntherさんのお2人がフルタイムで開発されているそうです。
（ずいぶん前に聞いた話なので今は違うかもしれません）

STFが生まれた経緯や、CyberAgent社内でどのように活用されているかなど、色々と興味深い話を聞かせて頂いたのですが、中でも一番印象に残っているのが社内ツールをOSSとして公開した理由です。

> 当初からSTFはOSSを視野に入れて開発していたんだ。
> ウチ（CyberAgent）は会社としてOSSを推奨しているから、社内からもとくに反対はなかったな。

> 僕自身もそうだけど、イマドキの開発者はOSSでないものを嫌うからね。
> それにもしOSSにしなければ、自分たちが異動や退社してプロジェクトに関われなくなった時、誰もメンテナンスできなくなってプロジェクトはいずれクローズしてしまう。そんなの悲しいよ。

> その点OSSなら、将来自分がどんな立場になっても「趣味として」外から携わり続けることができる。
> それに将来、STFを参考にしてもっと良いサービスが生まれたら、それはそれで嬉しいしね！

自身も [Chibineko](https://chibineko.jp/) というサービスをOSSで公開していますが、この考えにはとても共感しました。
たとえ仕事だったとしても自分で作ったモノには愛着があるので、何らかの形で携わり続け、成長を見守りたいという思いがあります。
ただのコンピュータ言語で書かれた無機質なモノなのに、不思議ですね。

と、話が少し脱線してしまいましたが・・・
このSTFはとても素晴らしいサービスなので、みなさんも是非触ってみてほしいです。
依存ツールが多目なので環境を作るのは少し大変かもしれませんが、READMEはとても丁寧に書かれているので興味のある方は一度トライしてみてください:grin: