涼風コンピュータblog

涼風 ・Rubyist, RubyやRuby on Railsに詳しくなっていきたいです

[翻訳] Android開発におけるベストプラクティス

[翻訳] Android開発におけるベストプラクティス

本稿はBest practices in Android development(fork)を翻訳したものです。 オリジナルはBest practices in Android developmentです。

要約

GradleとGradleで推奨されたプロジェクト構造を使用する

gradle.propertiesにパスワードと機密データを記述する

独自にHTTPクライントを実装せずに,VolleyまたはOkHttpライブラリを使用する

JSONデータの解析には、Jacksonライブラリを使用する

65,000メソッド制限のために,Guavaの使用を避け,2,3のライブラリのみを使用する

UI画面を表現するにはFragmentを使用する

Fragmentの管理のためだけにActivityを使用する

レイアウトXMLはコードであり,うまく整理する

レイアウトXMLではattributeの重複は避け,styleを使用する

一つの巨大なファイルは避け,複数のstyleファイルを使用する

colors.xmlは短く,DRYに保ち、パレットとしてのみ定義する

dimens.xmlもDRYに保ち, 一般的な定数を定義する

ViewGroupの階層を深くしない

WebViewでのクライアントサイドでの処理は避け,メモリリークに気をつける

ユニットテストにRobolectricを使用し, 接続(UI)テストにはRobotiumを使用する

エミュレータにはGenymotionを使用する

常にProGuardまたはDexGuardを使用する


Android SDK

Android SDKはホームディレクトリまたは他のアプリケーションに依存しない場所のどこかに置きましょう。インストール時にIDESDKを含んでいる場合は、IDEと同じディレクトリ配下にSDKがあるかもしれません。IDEをアップグレード(または再インストール)する時,またはIDEを変更する時にこれはよくないです。IDEルート権限下ではなく,ユーザー権限下で実行している場合は,sudoパーミッションが必要な別システムレベルのディレクトリに置くことも避けるべきです。

ビルドシステム

デフォルトのビルドはGradleにすべきです。AntはGradleに比べてかなり制限があり,冗長です。Gradleでは,次のように簡単です。

  • アプリのバリアントまたは異なったフレイバーをビルドする
  • 簡単なスクリプトのようなタスクを作る
  • 依存の管理とダウンロード
  • キーストアをカスタマイズする
  • 以上

AndroidのGradleのプラグインも積極的に新しい標準ビルドシステムとしてGoogleによって開発されています。

プロジェクト構造

2つの人気の選択肢があります。: 古いAnt&Eclipse ADTプロジェクト構造と新しいGradle&Android Studioプロジェクト構造です。新しいプロジェクト構造を選ぶべきです。古い構造を使用する場合は,それはレガシーと考え,新しい構造に移植を始めましょう。

古い構造:

old-structure
├─ assets
├─ libs
├─ res
├─ src
│  └─ com/futurice/project
├─ AndroidManifest.xml
├─ build.gradle
├─ project.properties
└─ proguard-rules.pro

新しい構造:

new-structure
├─ library-foobar
├─ app
│  ├─ libs
│  ├─ src
│  │  ├─ androidTest
│  │  │  └─ java
│  │  │     └─ com/futurice/project
│  │  └─ main
│  │     ├─ java
│  │     │  └─ com/futurice/project
│  │     ├─ res
│  │     └─ AndroidManifest.xml
│  ├─ build.gradle
│  └─ proguard-rules.pro
├─ build.gradle
└─ settings.gradle

主な違いは新しい構造が明確にGradleから'ソースのセット' (main, androidTest)と概念を分けていることです。例えば, アプリのpaidとfreeフレイバー用のソースコードを持つ'paid'と'free'のソースセットを追加したとしましょう。

トップレベルのappは アプリを参照している他のライブラリ(例:library-foobar)からアプリを区別することに役立ちます。それから,settings.gradleapp/build.gradleが参照することができるライブラリプロジェクトを参照を保持します。

Gradle 設定

一般的な構造 Google's guide on Gradle for Androidを参照してください。

小さなtask (shell, Python, Perlなど)スクリプトのかわりにGradle上でtaskを作成することができます。詳しくは,Gradle's documentationを参照してください。

パスワード アプリのbuild.gradleに, リリースビルド用にsigningConfigsを定義する必要があります。

以下のようにしないでください。これはバージョンコントロールシステムに出てきます。

signingConfigs {
    release {
        storeFile file("myapp.keystore")
        storePassword "password123"
        keyAlias "thekey"
        keyPassword "password789"
    }
}

かわりに, バージョンコントロールシステムに追加すべきでないgradle.propertiesファイルを作成します。

KEYSTORE_PASSWORD=password123
KEY_PASSWORD=password789

このファイルはgradleによって,自動的にインポートされます。それから, 次のようなにbuild.gradleでパスワードを使用できます。

signingConfigs {
    release {
        try {
            storeFile file("myapp.keystore")
            storePassword KEYSTORE_PASSWORD
            keyAlias "thekey"
            keyPassword KEY_PASSWORD
        }
        catch (ex) {
            throw new InvalidUserDataException("You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.")
        }
    }
}

jarファイルをインポートする代わりに, Mavenの依存解決が好ましい 明らかにプロジェクトにjarファイルを含めている場合は, jarは2.1.1のような指定された固定バージョンになるでしょう。jarファイルのダウンロードし, 更新処理することは面倒です。これはMavenが適切に解決する問題で, Android Gradleビルドでも推奨されています。2.1.+のようにバージョンの範囲を指定することができ, Mavenは自動的にパターンマッチングを行い,最新バージョンへの自動更新を取り扱います。

dependencies {
    compile 'com.netflix.rxjava:rxjava-core:0.19.+'
    compile 'com.netflix.rxjava:rxjava-android:0.19.+'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.4.+'
    compile 'com.fasterxml.jackson.core:jackson-core:2.4.+'
    compile 'com.fasterxml.jackson.core:jackson-annotations:2.4.+'
    compile 'com.squareup.okhttp:okhttp:2.0.+'
    compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.+'
}

IDEテキストエディタエディタ

どんなエディタを使用しても,プロジェクトの構造とうまく連携しなければならりません エディタは個人的な選択で,エディタがプロジェクト構造とビルドシステムによって機能するかはあなたの責任です。

現時点で最も推奨されるIDEAndroid Studioです。なぜなら,Android StudioGoogleによって開発されていて,Gradleに最も近く,デフォルトで新しい構造を使用しており,ベータ版の最終段階で,Android開発用だからです。

Eclipse ADTを望むなら,使用することができますが,古いプロジェクト構造でありAntビルドであることが想定されるので,Eclipse ADTを設定する必要があります。Vim,Sublime Tex,Emacsのような平文テキストエディタも使用することができます。この場合では,コマンドラインからGradleとadbを使用する必要があります。Gradleを使用したEclipseのインテグレーションが機能しない場合は,ビルドするためにコマンドラインを使用するか, Android Studioに移行してください。

何を使用するであれ,Gradleと新しいプロジェクト構造がアプリをビルドする公式的な方法のままであることを確認し,バージョンコントロールシステムにエディタ指定の設定を追加することは避けましょう。例えば,Ant build.xmlファイルを追加することは避けましょう。特に,Antでビルド設定を変更している場合は,build.gradleを最新に維持し,機能するようにすることを忘れてはいけません。また,他の開発者に親切にし,他の開発者にツールの好みを強制することも避けましょう。

ライブラリ

JacksonはオブジェクトからJSONの変換と逆変換するJavaライブラリです。Gsonはこの問題を解決するために人気の選択肢です。しかしながら, JSONを処理するのに別な方法(ストリーミング,インメモリtreeモデルと伝統的なJSON-POJOデータバインディング)をサポートしているので,Jacksonはよりパフォーマンスがよいです。JacksonはGSONより大きなライブラリですが場合によって6,5000メソッド制限を避けるためGSONを好むことをもよいかもしれません。他の代替はJson-smartBoon JSONです。

ネットワーク,キャッシュ,画像 あなた自身のクライアントに実装するか考慮すべきバックエンドサーバにリクエストする2つの実証済みの解決方法があります。VolleyまたはRetrofitを使用しましょう。Retrofitを選択する場合は,画像のロードとキャッシュにはPicasso,効率的なHTTPリクエストにはOkHttpを考えましょう。すべての3つのRetrofit,Picasso,OkHttpは同じ会社によって作成されていますので,3つのライブラリはお互いうまく補完しています。OkHttpも Volleyと接続して使用できます。

RxJavaはReactiveプログラミングのためのライブラリです。言い換えると,非同期イベントを処理するためのライブラリです。強力かつ有望なパラダイムで,だいぶ異なるので混乱することもあります。すべてのアプリケーションに構築する前にこのライブラリを使用する前に注意することをおすすめします。私たちによってRxJavaを使用し完了したいくつかのプロジェクトがあります。もしあなたが次の人々(Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen)の一人の間助言が必要なら。私たちは次のブログにブログを書いています。: [1], [2], [3], [4]

以前Rxの経験が全くなければ, APIからのレスポンスだけにRxを適用することから始めましょう。あるいは,クリックイベントや検索領域でのタイピングイベントのような簡単なUIイベント処理にRxを適用することから始めましょう。あなたがRxスキルに自身を持っていてすべてのアーキテクチャに適用したいならすべてのトリック部分をJavadocに書きましょう。

RetrolambdaAndroidと他のJDK8以前のプラットフォームでラムダ表現シンタックスを使用するためのライブラリです。このライブラリは特にRxJavaのような関数スタイルを使用する場合に,コードを頑丈かつ読みやすくします。このライブラリはを使用するためにJDK8をインストールし,Android Studioプロジェクト構造ダイアログでSDK LocationとしJDK8を設定し, JAVA8_HOMEJAVA7_HOME環境変数を設定し, それからプロジェクトルートでbuild.gradleを次のようにしてください。

dependencies {
    classpath 'me.tatarka:gradle-retrolambda:2.4.+'
}

各々のモジュール build.gradleに次のように追加してください。

apply plugin: 'retrolambda'

android {
    compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

retrolambda {
    jdk System.getenv("JAVA8_HOME")
    oldJdk System.getenv("JAVA7_HOME")
    javaVersion JavaVersion.VERSION_1_7
}

Android StudioはJava8ラムダに関するコードアシスタントサポートを提供します。あなたがラムダを初めて使用する場合は,始めるために次を使用してください。

  • ただひとつのメソッドを持つインタフェースはラムダフレンドリーで,より狭いシンタックスに折りたたむことができます。

  • パラメータに疑いがある場合, 通常の匿名インナークラスを書き, Android Studioがあなたのためにそれをラムダに折りたたみます。

dexメソッド制限に気をつけ, 多くのライブラリを使用することは避けましょう。 Androidアプリはdexファイルとしてパッケージされているとき, 65535個のリファレンスメソッド([1] [2] [3])の厳しい制限があります。制限を超えている場合,コンパイル時に致命的なエラーに遭遇するでしょう。そのため,最小限のライブラリを使用し,制限下でどのライブラリセットを使用できるか決定するdex-method-countsツールを使用しましょう。特にGuavaライブラリを使用することは避けましょう。なぜなら,Guavaライブラリは13,000以上のメソッドを含んでいるからです。

ActivityとFragment

FragmentAndroidでUI画面を実装するためのデフォルトの選択肢とすべきです。ユーザーインタフェース画面を表現するactivityの代わりにfragmentを使用することを推奨します。ここにいくつかの理由を示します。

  • multi-paneレイアウトのための解決方法 携帯電話アプリケーションをタブレット画面に拡張するために主目的に導入されましたので,タブレット画面でpane AまたBのどちらかがすべての携帯電話画面を占有している時, pane AとBの両方を持つことができます。あなたのアプリケーションがはじめからFragmentで実装されている場合,あたなのアプリケーションをことなったフォームファクタに適用することはあとで簡単になります。

  • 画面間の通信 AndroidAPIはあるActivityから別なActivityへの複雑なデータ(例: いくつかのJavaオブジェクト)を送信する適切な方法を提供していません。しかしながら,Fragmentとでは,子Fragmentとの間で通信のチャンネルとしてActvityのインスタンスを使用することができます。たとえ,これはActivityからActivityへの通信より良いとしても,あなたはより明瞭な方法として,イベントバスアーキテクチャ(例: Ottoまたはgreenrobot EventBus)を考慮したいかもしれません。あなたがさらもう一つのライブラリを追加することを避ける場合に,RxJavaはイベントバスを実装するために使用することもできます。

  • FragmentはUIだけでなく一般的に十分です。 UIなしのfragmentActivity用にバックグランドワーカーとして機能します。あなたはActivityにロジックを持つ代わりに, fragment to contain the logic for changing fragmentsを生成するという考え方を持つことができます。

  • ActionBarはFragment内で管理することができます。 ActionBarを管理する目的のみでUIなしの1つのFragmentを持つか, 各々の見えているFragmentが親ActivityのActionBarに自身のアクションアイテムを追加するかを選択することができます。詳細はここ.

そうはいっても, 私たちは広範囲に入れ子のfragmentを使用するように助言しません。なぜなら,matryoshka bugsが起こりうるからです。入れ子のfragmentは理にかなっているとき(例: Fragmentのような画面内に水平スライディングViewPagerないのFragmentだけ),または十分な情報での決断の場合です。

アーキテクチャレベルでは, あなたのアプリは多くのビジネス関するFragmentを含んでいるトップレベルのActivityを持つべきです。メインActivityとの通信が単純でIntent.setData()) または Intent.setAction())が制限されるかまたは類似の場合に限り,他の支援するActivityも持つことができます。

Javaパッケージアーキテクチャ

Androidに関するJavaアーキテクチャはおおよそModel-View-Controllerに近いです。AndroidではFragmentとActivityは実際にはコントローラークラスです。 一方, FragmentとActivityは明示的にユーザーインターフェースの部分ですから,Viewでもあります。

このため, Fragment(またはActivity)を厳密にコントローラーとビューに分類することは難しいです。Fragmentはfragmentsパッケージに置くことがより良いです。前のセクションに従う限りは,Activityはトップレベルに置くことができます。2つまたは3つ以上のActivityを持つ予定なら,activitiesパッケージも作成しましょう。

そうでなければ,アーキテクチャAPIレスポンスでJSONパーサーを通して入ったPOJOを含むmodels, あなたのカスタムView, 通知, action bar view, widgetなどを含むviewを持った典型的なMVCのように見えることができます。 Adapterはグレー要素で, データとViewの間に存在します。しかしながら, それらは典型的にgetView()経由で外出しする必要があるので, あなたはviews内のサブパッケージにadaptersを含むことができます。

いくつかのコントローラークラスはアプリケーション全体であり,Androidシステムに近いです。それらはmanagersパッケージに置くことができます。「DateUtils」のような雑多なデータ処理クラスはutilsパッケージに置きます。バックエンドで通信する役割のクラスはnetworkパッケージに置きます。

All in all, ordered from the closest-to-backend to the closest-to-the-user:

com.futurice.project
├─ network
├─ models
├─ managers
├─ utils
├─ fragments
└─ views
   ├─ adapters
   ├─ actionbar
   ├─ widgets
   └─ notifications

リソース

名前付け type_foo_bar.xmlのように接頭語に型を付ける慣例に従いましょう。例 : fragment_contact_details.xml, view_primary_button.xml, activity_main.xml.

layout XMLを整理する レイアウトXMLの書式化する方法に自信がなければ, 次の慣例が役に立つかもしれません。

  • 一行につき一つの属性で, 4つの空白のインデントにします。
  • はじめの属性はいつもandroid:idにします。
  • android:layout_****属性は上部に置きます。
  • style属性は下部に置きます。
  • 属性の順序の入れ替えと追加を容易にするために, 単独の行に閉じタグ/>を置きます。
  • android:textにハードコーディングするよりむしろ, Android Studioで使用できるDesigntime attributesを使用することを考えてください。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="@string/name"
        style="@style/FancyText"
        />

    <include layout="@layout/reusable_part" />

</LinearLayout>

大体, android:layout_****属性はレイアウトXMLに定義すべきで,一方他のandroid:****属性はスタイルXMLに定義すべきです。このルールには例外があるが, 一般的にはうまく機能します。この考えはレイアウトファイルにレイアウト(位置, マージン, サイズ)とコンテンツ属性だけを置き, 一方スタイルファイルにすべての見た目の詳細(色, パディング, フォント)を置きます。

例外は

  • android:idは明らかにレイアウトファイルに置くべきです。
  • LinearLayout用のandroid:orientationは通常レイアウトファイルに置くことが理にかなっています。
  • android:textはレイアウトファイルに置くべきです。なぜならそれはコンテンツを定義するからです。
  • ときどきデフォルトでandroid:layout_widthandroid:layout_heightはレイアウトファイルにあるべきですが, 一般的なスタイルがandroid:layout_widthandroid:layout_heightを定義することは理にかなっているでしょう。

スタイルを使用する。 ほとんどのプロジェクト毎に適切なスタイルが必要になります。なぜなら、ビューに関して繰り返しの外観を持つことはとても一般的であるからです。少なくとも、アプリケーションで最も多いテキストコンテンツに関する共通スタイルを持つべきです。たとえば

<style name="ContentText">
    <item name="android:textSize">@dimen/font_normal</item>
    <item name="android:textColor">@color/basic_black</item>
</style>

TexTiewに適用します。

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/price"
    style="@style/ContentText"
    />

あなたはたぶん,ボタンに関して同じことをするでしょう。しかし,そこではまだしません。そこを通り越して、関係しているグループと繰り返されるandroid:****属性は共通スタイルに移動させましょう。ビルドシステムにおいていくつかの意味を持つリソースディレクトリ名とは異なり,res/valuesにあるファイル名は任意にすることができます。

大きなスタイルファイルは他のファイルに分けましょう。 一つのstyles.xmlにする必要はありません。Android SDKは形にとらわれない他のファイルをサポートしています。stylesに関して魔法は何もありません。肝心なところはファイル内のXMLタグ<style>です。したがって、あなたはstyles.xml, styles_home.xml, styles_item_details.xml, styles_forms.xmlを持つことができます。

colors.xmlはカラーパレットです。 colors.xmlでカラー名とRGBA値にマッピング以外に他になにかあってはならいです。違ったタイプのボタンに関してRGBA値を定義するcolors.xmlを使用することは止めましょう。

このようにはしない:

<resources>
    <color name="button_foreground">#FFFFFF</color>
    <color name="button_background">#2A91BD</color>
    <color name="comment_background_inactive">#5F5F5F</color>
    <color name="comment_background_active">#939393</color>
    <color name="comment_foreground">#FFFFFF</color>
    <color name="comment_foreground_important">#FF9D2F</color>
    ...
    <color name="comment_shadow">#323232</color>
  • 代わりにこのようにします:
<resources>

    <!-- grayscale -->
    <color name="white"     >#FFFFFF</color>
    <color name="gray_light">#DBDBDB</color>
    <color name="gray"      >#939393</color>
    <color name="gray_dark" >#5F5F5F</color>
    <color name="black"     >#323232</color>

    <!-- basic colors -->
    <color name="green">#27D34D</color>
    <color name="blue">#2A91BD</color>
    <color name="orange">#FF9D2F</color>
    <color name="red">#FF432F</color>

</resources>

このパレットはアプリケーションのデザイナーにお願いしましょう。この名前は"green", "blue"などのようなカラー名は必要ありません。"brand_primary", "brand_secondary", "brand_negative"のような名前も完全に許容可能です。色をフォーマットすることはそれ自体,色を変更またはリファクタしやすく, どのくらい違った色が使用されているかが明白になるでしょう。通常,美しいUIのためには、さまざまな色が使用されることを減らすことが重要です。

colors.xmlのようにdimens.xmlを扱う。 あなたは色の場合と基本的に同じ目的のために, 典型的な空白とフォントサイズの"パレット"も定義すべきです。dimensファイルのよい例は:

<resources>

    <!-- font sizes -->
    <dimen name="font_larger">22sp</dimen>
    <dimen name="font_large">18sp</dimen>
    <dimen name="font_normal">15sp</dimen>
    <dimen name="font_small">12sp</dimen>

    <!-- typical spacing between two views -->
    <dimen name="spacing_huge">40dp</dimen>
    <dimen name="spacing_large">24dp</dimen>
    <dimen name="spacing_normal">14dp</dimen>
    <dimen name="spacing_small">10dp</dimen>
    <dimen name="spacing_tiny">4dp</dimen>

    <!-- typical sizes of views -->
    <dimen name="button_height_tall">60dp</dimen>
    <dimen name="button_height_normal">40dp</dimen>
    <dimen name="button_height_short">32dp</dimen>

</resources>

あなたは文字列を通常扱うように, 値をハードコーディングする代わりにマージンとパディングでレイアウトのspacing_**** の大きさをを使用すべきです。これは一貫性のあるルック&フィールを与えると同時にスタイルとレイアウトを整理や変更使用すくなります。

viewsの深い階層を避ける。 ときどきあなたはビューを整理するために,ただ,さらにもう一つのレイアウトを追加したくなるかもしれません。この主の状況は起こるかもしれません:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <RelativeLayout
        ...
        >

        <LinearLayout
            ...
            >

            <LinearLayout
                ...
                >

                <LinearLayout
                    ...
                    >
                </LinearLayout>

            </LinearLayout>

        </LinearLayout>

    </RelativeLayout>

</LinearLayout>

たとえあなたはレイアウトファイルで明示的にこれを目撃しないとしても,あなたが他のビューの中にビューを(Javaで)追加するならそれは起こって終わるかもしれません。

2つの問題が起こるかもしれません。あなたは性能問題を経験するかもしれません。プロセッサは制御が必要な複雑なUIツリーがあるからです。もう一つの深刻な問題はStackOverflowErrorの可能性です。

それゆえ, できる限りビュー階層を平らに維持しましょう: RelativeLayoutを使用する方法, optimize your layoutsする方法と<merge> tagを使用することを学びましょう。

WebViewに関する問題について注意しましょう。 例えば,ニュース記事のようなWebページを表示しなければならないとき,クライアント側がHTMLをきれいにする処理をするうことは避け, むしろバックエンドプログラマー純粋なHTMLを要求しましょう。ApplicationContextにバインドされる代わりに,WebViewがActivityの参照を保持するとき,WebViews can also leak memory。簡単なテキストまたはボタンのためのWebViewを使用することを避け, TextViewまたはButtonを使用しましょう。

テストフレームワーク

Android SDKのテストフレームワークはまだ幼児です。特にUIテストに関するものがそうなります。Android Gradleは現在作成したJUnitテストを実行するconnectedAndroidTestと呼ばれるテストタスクを実装しています。また,extension of JUnit with helpers for Androidを使用しています。これはデバイスまたはエミュレータに接続してテストを実行する必要があることを意味しています。テストに関する公式ガイド[1] [2]に従いましょう。

ViewではなくユニットテストだけにRobolectricを使用する。 Robolectricは開発スピードのために"デバイスに接続していない"テストを提供しようとするテストフレームワークです。特にモデルとビューモデル上のユニットテストに適しています。しかしながら, Robolectric下でのテストはUIに関して不正確で不完全です。あなたはダイアログ,アニメーションなどに関するUI要素をテストする問題を持っているでしょう。これはあたなが「暗闇の中を歩いている。」(制御される画面を見ることなくテストすること)という事実によって複雑になるでしょう。

RobotiumはUIテストを記述することを簡単にします。 あなたはUIケースの接続テストを実行するためにRobotiumは必要ありませんが, それはビューの取得または分析と画面制御する多くのヘルパーがあるため,たぶんあなたに利益をもたらします。テストケースは次のように簡単です:

solo.sendKey(Solo.MENU);
solo.clickOnText("More"); // searches for the first occurence of "More" and clicks on it
solo.clickOnText("Preferences");
solo.clickOnText("Edit File Extensions");
Assert.assertTrue(solo.searchText("rtf"));

エミュレータ

あなたがAndroidアプリをプロとして開発する場合は,Genymotion emulatorのライセンスを購入しましょう。 Genymotionエミュレータは典型的なAVDエミュレータより毎秒フレームレートが速く実行します。それらはアプリをデモするまたはネットワーク接続品質とGPS位置のエミュレートするなどのツールを持っています。それらは接続テストにも最適です。あなたは多くの(全てではなく)異なったデバイスにアクセスするので, Genymotionのライセンスの費用は複数の実デバイスを買うより実際はかなり安いです。

注意事項: GenymotionエミュレータGoogle PlayストアとMapsのような全てのGoogleサービスを提供するわけではありません。あなたはサムスン仕様のAPIをテストするかもしれません。そのときはリアルサムスンデバイスを所有する必要があります。

Proguard構成

ProGuardは通常パッケージ化されたコードを縮小し,難読化するためにAndroidプロジェクト上で使用されます。

あなたがProGuardを使用するかしないはあなたのプロジェクト構成に依存します。通常,リリースapkをビルドするときProGuardを使用しするようにgradleを構成するでしょう。

buildTypes {
    debug {
        runProguard false
    }
    release {
        signingConfig signingConfigs.release
        runProguard true
        proguardFiles 'proguard-rules.pro'
    }
}

どのコードが予約されなけらばならないか,どこのコードが捨てるかまたは難読化されるかを決定するために, あなたはコードに1つ以上エントリーポイントを指定しなければなりません。それらのエントリーポイントは典型的な主なmethod, applet, midlet, activityなどを含むクラスです。 AndroidフレームワークSDK_HOME/tools/proguard/proguard-android.txtに記述されたデフォルト構成を使用します。カスタムプロジェクト指定proguardルールは(my-project/app/proguard-rules.proに定義されるような)デフォルト構成に追加されます。

ProGuardに関係した共通問題はClassNotFoundException, NoSuchFieldExceptionまたはそれに似たもので始まるアプリケーションクラッシュを見ることです。たとえ,ビルドコマンド(例 assembleRelease)が警告なしに成功しても見ましょう。 これは2つのうちのいずれかを意味します:

  1. ProGuardは必要ないと考えられるクラス, 列挙(enum), メソッド, フィールドまたはannotationは削除します。
  2. ProGuardはクラス, 列挙(enum)またフィールド名は難読化(リネイム)されますが, それは元の名前たとえばJavaリフレクションをによって間接的に使われています。

問題のオブジェクトが難読化されているを確かめるためにはapp/build/outputs/proguard/release/usage.txtを調べてください。

ProGuardが必要なクラスまたはクラスメンバを取り除くことを防ぐためには, あんたのproguard設定にkeepオプションを追加します:

-keep class com.futurice.project.MyClass { *; }

ProGuardがクラスまたはクラスメンバを難読化することを防ぐにはkeepnamesを追加します:

-keepnames class com.futurice.project.MyClass { *; }

例はthis template's ProGuard configを調べてください。

例はさらにProguardを参照してください。

Tip。 あなたがユーザーに公表しているリリース毎のmapping.txtファイルを保存します。各リリースビルド用のmapping.txtファイルのコピーを保持することにより, ユーザーがバグに遭遇し, 難読化されたスタックトレースを送信するなら, あなたはあなたが問題をデバッグすることがでることを保証します。

DexGuard。 もしあなたが最適化されたハードコアツールと特別な難読化リリースコードが必要なら, ProGuardをビルドする同じチームが作成した商用ソフトウェアであるDexGuardを考慮してください。それは65000メソッド制限を解決するためにDexファイルを簡単に分割することもできます。

謝辞

Antti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton とAndroid開発に関する知識を共有するう他のFuturice開発者に感謝します。

ライセンス

Futurice Oy Creative Commons Attribution 4.0 International (CC BY 4.0)

Jun Hiroe Creative Commons Attribution 4.0 International (CC BY 4.0)