Android再入門 〜Eclipseのことは忘れろ〜 #nds40


※本記事は、[長岡IT開発者勉強会#40 初心者Day](http://nagaoka.techtalk.jp/no40)で話す内容のドラフトとして書かれたものです。
※本記事は、2015年2月時点での技術に関する時事ネタを多分に含んでいます。ご留意ください。

2/26 この記事のメイキング記事を[書きました](http://blog.nkzn.info/entry/2015/02/26/234926)。

はじめに
----------

Androidが世に出た2008年秋からもうすぐ7年が経とうとしています。日本で初めてのAndroidスマートフォンである[HT-03A](http://www.htc.com/jp/smartphones/htc-magic/)がドコモから発売された2009年夏からは、もうすぐ6年です。「ツートップ戦略」が記憶に新しいXperiaやGalaxy Sシリーズが出始めたのは2010年ですから、そこからも5年は経とうとしています。

十年一昔、という言葉がありますが、Web方面に関わっていると三年一昔という言葉が脳裏をよぎることすらあります。7年足らずの歴史しか持たないAndroidにとっても、3年という時間は半生と呼ぶに差し支えないものでしょう。

3年前の情報の中には、現在でも使えるものと、現在では鵜呑みにできなくなったものが混在しています。今回は初心者Dayということで、これからAndroidを学んでいこうと思っている人向けに、私が普段の作業をしている中で見つけた情報の取捨選択の基準にしているものを紹介します。

昔のAndroidアプリ開発キーワード
----------

* Eclipse + ADT
* 公式Emulator (or Intel HAXM)
* UI以外のテストをJUnit3で動かす
* Ant? 知らない子ですね
* Maven? うっ、頭が・・・

普通にアプリ開発をしている分には、だいたいこの辺のキーワードが出てきたら古いと判断してそっ閉じしていいです。エミュレータは用途によっては現在でも利用したほうが良い場合もあります。

今のAndroidアプリ開発キーワード
----------

* [Android Studio](http://developer.android.com/sdk/index.html)
* [Gradle](https://developer.android.com/tools/building/plugin-for-gradle.html)
* JUnit4
* [Espresso 2.0](https://code.google.com/p/android-test-kit/wiki/Espresso)
* [Robolectric](http://robolectric.org/)
* [Genymotion](https://www.genymotion.com/)
* おまけ：[WaterCell/android-app-template](https://github.com/WaterCell/android-app-template)

各キーワードについてあれこれ
----------

### Eclipse + ADT -> Android Studio

開発環境についての話題を調べていると、恐らくEclipseや、EclipseのADT(Android Developer Tool)プラグインを導入する話が出てくると思いますが、無視してください。[「公式IDEはもうAndroid Studioなんだぜ？ 移行手順書作ってあるからさ、手持ちのプロジェクト移管しようぜ。な？」](http://developer.android.com/tools/help/adt.html)とGoogle様が仰っているので、素直にAndroid Studioを使いましょう。

### ビルドツールはGradle一択

Gradleはビルドツールの一種です。Gradle自体はAndroid Studioに依存していないため、ターミナルで

```bash
$ ./gradlew clean check assembleDebug
```

のようなコマンドを叩くと、アプリの実体であるAPKをテストしたりビルドすることができます。コマンドラインから実行できるので、将来JenkinsやTravis CIなどを使って「ソースが更新された時に自動でテストを実行してくれる」ような仕組みを作る際に、簡単に移行できるようになります。

AntやMavenでAndroidをビルドする話も見つかることがあるかもしれませんが、古い方法なのでそっ閉じしましょう。このへんの話は[僕がEclipseをやめてAndroid Studioを使っている10の理由](http://blog.nkzn.info/entry/2014/03/21/015914)という記事で言及していますので、よろしければお読みください。

ただ、Android Studioは[12月9日にバージョン1.0が出た](http://googledevjp.blogspot.jp/2014/12/android-studio-10.html)ばかりで、Gradleプラグインもほぼ同じタイミングでバージョンアップしていますので、1.0未満の時代の情報がまだまだ多く見つかります。

バージョン0.6未満では`packageName`という名前だったものが0.6以降は`applicationId`という名前になっていたりと、１年前の情報でも現在では使えなくなっているものがあったりします。1.0以降は更新が穏やかになると思いますので、できるだけ2014年12月以降の情報を狙って探すようにしましょう。

また、ライブラリの依存関係を解決する際に自動でダウンロードを行うため、ネットワークが貧弱なサーバーや、ちょっと融通がきかないプロキシを通している環境でも採用が難しいところではあります。

### エミュレータ

| エミュレータ      | 速度    | CPU | Play Services |
|-----------------|---------|-----|---------------|
|公式エミュレータ    |すごく遅い|ARMv7|Android4.2以降なら搭載版あり       |
|Intel版エミュレータ|実機くらい早い    |x86  |搭載版なし       |
|Genymotion       |実機より早い|x86   |後のせ可（無保証）     |

* Android NDKでC++やgolangを使って開発する場合はARMv7 CPUを積んでいるエミュレータでないと実行できない
	* GenymotionにもARM Translationプラグインがあるので、一応動くらしい
	* まあそもそも実機使ったほうが早くない？とも思う
* Googleマップやアプリ内課金、プッシュ通知などの、Google依存なサービスを扱うには **Google Play開発者サービス**を積んでいることが必須
	* Android 4.2(API17)以降のエミュレータなら搭載版がある
	* Genymotionも裏ワザ的に後から載せられる
	* まあそもそも実機使ったほうが早くない？とも思う

### テストツール

#### 公式UIテストツール（androidTest）

公式のUIテストツールに関しては、JUnit3からJUnit4への過渡期にありますが、基本的なテストの手法は変わらないため、書籍などでも少し読みかえれば現在でも使える手法は多いと思います。

ただ、公式テスト便利ライブラリであるEspressoがバージョン1.1から2.0に上がった段階でjar配布からMaven配布に変わったため、導入のところは少し変わっています。

#### 非公式ユニットテストツール（Robolectric）

ところで、上記のテストツールはエミュレータや実機上でしか動かないため、実行までにそれなりに時間がかかります。UIが絡まないユニットテストをするには、ちょっと嫌です。

ユニットテストを行いたい場合は、Robolectricを使って、手元のJVM上で高速にテストを回すといいでしょう。

#### 実例

弊社製の[WaterCell/android-app-template](https://github.com/WaterCell/android-app-template)では、公式UIテストツールとRobolectricを併存させながら、テストを通しています。

JUnit4を用いるとこういうユニットテストができるよ、みたいな話は下記の本が詳しいので、是非お読みください。

[Amazon.co.jp： JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus): 渡辺 修司](http://amzn.to/1z5KUqL)

Android Javaについて留意しておいたほうがいいこと
----------

「AndroidアプリはJavaで動いている」は全く間違いだとは言いませんが、ちょっと思い切りが良すぎる言葉です。Oracle JavaともOpenJDKとも違う特殊な有り様は、しばしば「Android Java」という言葉で揶揄されます。

Androidで扱える「Javaの文法」と「Javaの標準ライブラリ」は、動作対象のAndroidバージョンによっては一致しないことがあります。具体的にはJava7の文法が一部しかサポートされていない事例です。

例えば、Android 4.2環境向けに、Java7で開発がしたいと思ったら、Gradleで下記の設定を書けばいいだけです。

```gradle:build.gradle
android{
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
}
```

この場合、データベースやネットワークのクローズ処理を自動で行ってくれるtry-with-resourcesというJava7の目玉機能の一つを使えない状況になります。これは、Android 4.4 Kitkat以降でしか動作させないことを明示しないと、使えない文法なのです。

また、同様に、KitKat以降で動作させることを明示しないと、`java.lang.Long.compare(long lhs, long rhs)`のような、Java7で新登場した標準ライブラリが使えなかったりもします。これはAPI Level 19で提供されたメソッドである、というだけの扱いなので、不思議ではないといえばそうなのですが、Java7のつもりで触っていると、少し気持ち悪い部分ではあります。

一方、`new ArrayList<>()`のような書き方でジェネリクスの型パラメータを省略できる **ダイヤモンド演算子** の機能が入ったコードなどは、Android 2.3などでも動作します。Oracle Java/OpenJDKの経験者の方は、Androidのコードを眺める際には特定のJavaバージョンを想定せずに、[リファレンス](http://developer.android.com/reference/packages.html)でAPI Levelを見ながら使えるメソッドを探すとよいでしょう。

### Java7指定でできることまとめ

* API, try-with-resources
	* Android 4.4 KitKatから
* その他の文法
	* Android 2.3までは動く（検証済み）

### 参考：OSビルド時のJavaバージョン

実行環境のバージョンとは少しずれていますが、OS自体をビルドする場合に必要とされるJavaのバージョンが記載された資料を見つけました。

| Androidバージョン | OSビルドに必要なJavaのバージョン |
|-----------------|---------------------|
|Android 1.5〜2.2 |Java 5        |
|Android 2.3〜4.4 |Java 6        |
|Android 5.0〜    |Java 7        |

http://source.android.com/source/initializing.html#installing-the-jdk

Oracle Javaでは[Java6で新登場](https://docs.oracle.com/javase/jp/6/api/java/lang/String.html#isEmpty())した[String#isEmpty()](http://developer.android.com/reference/java/lang/String.html#isEmpty())がAPI Level 9(Android 2.3)以降で対応しているという点では、ある程度この表に沿った形でAPI Levelごとの標準ライブラリの実装が進んでいると思ってよさそうです。

何故Android 4.4はJava6ビルドなのにJava7の標準ライブラリを積んでるんだろう・・・。

Android SDKについての記事全般
----------

### APIについての記事

Androidは下位互換性が崩されるケースがあまりないので、昔の記事にある書き方で動かないということはあまりありません。

ただ、support-v4やappcompat-v7のようなAndroid Support Libraryシリーズで、よりスマートな書き方が提示される場合もありますので、同じことを実現しようとした場合でも、古い情報と新しい情報で書き方が違っている場合があります。

### ProGuard, Lintについての記事

逆コンパイル対策の難読化や、使っていないメソッド・クラスの削除をしてくれる難読化ツール「ProGuard」。Androidアプリ開発のベストプラクティスの推奨や保守性向上のための指摘をしてくれる静的解析ツール「Android Lint」。

これらは誕生時点からあまり形が変わっていないため、多少古い情報であっても活用できる部分が多いでしょう。

ライブラリを探すとき
----------

GitHubなどでライブラリを探すことになると思いますが、Star数などの評価よりも、開発が活発に続いているかなどのほうを重視したほうが良さそうです。

というのも、大量のStarが付いているライブラリでも、Deprecated（非推奨）になっていて、開発が放棄されている可能性があるからです。

* [JakeWharton/ActionBarSherlock](https://github.com/JakeWharton/ActionBarSherlock)(★6630)

Googleはデファクトスタンダードになったライブラリと似たような動作をするものを積極的にSupport Libraryの形で提供するため、サードパーティ製ライブラリの存在意義が無くなり、開発が止まってしまうことが多々あります。

公式ライブラリがある場合は、できるだけ公式のものを使うようにしましょう。（カスタマイズ性あたりと相談ですが）

まとめ
----------

私の観測範囲における、Android界隈の近況報告みたいな記事になりました。

宣伝１
----------

ウォーターセル株式会社では、農業分野でのITツールの開発・改善に一緒に取り組んでくれるAndroidエンジニアを募集しています。

農業IT分野がどんなものなのか話を聞いてみたいレベルでも結構ですので、興味のある方は@Nkznまで空リプを飛ばすなり何なりして、コンタクトを取っていただければと幸いです。

宣伝２
----------

4月25日(土)に、渋谷のサイバーエージェントを会場にして、[DroidKaigi](http://droidkaigi.github.io/)という技術特化な開発者のためのカンファレンスが行われます。

Call For Papers(スピーカー申し込み)は2月25日までなので、Androidの何らかのレイヤーで喋ってみたいことがある方は是非お申込みください。

http://droidkaigi.github.io/#cfp