【Android】もっと先へ「加速」したくはないか、少年 〜Project Template編〜


今回は新規プロジェクトを作成する際に、毎回同じパッケージ構成をしている、毎回同じファイル作ってるという方向けの投稿です。

少しだけ裏技チックな手法を使います。

##前置き

github上で最近★を集めていてAndroidのベストプラクティスについ触れている[android-best-practices](https://github.com/futurice/android-best-practices) をご存知でしょうか？

ここではpackage構成は下記が良いと言っています。

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

私はこれに少しカスタマイズしたものを採用しております。

少しだけ説明すると、MVC + 3層レイヤーをAndroidで構築すると下記のようになるという考えを持っているので、

<img src="https://qiita-image-store.s3.amazonaws.com/0/47114/3e8d47d7-7e74-1d1d-a9dd-9aceb18f76ca.png" width=600 />

これに基づいて、package構成は下記のようにしています。

```
com.kugimiya.project
├─ network
├─ models
|  ├─ entities
|  ├─ prefs
|  ├─ apis
|  └─ provider
├─ utils
├─ fragments
├─ services
└─ views

```

加えてプロジェクトを新規で作るとほぼほぼSettingのPreferenceを作るので、新規プロジェクト作成時には毎回下記のようなところまでやって組み始めてました。

```
com.kugimiya.project
├─ network
├─ models
|  ├─ SettingModel.java
|  ├─ entities
|  |   └─ Setting.java
|  ├─ prefs
|  |   └─ SettingPrefs.java
|  ├─ apis
|  └─ provider
├─ utils
├─ fragments
├─ services
└─ views

```

毎回やってるなら自動化したい。そういう思いでいろいろ探したり試行錯誤していると見つけました。

Project Templateを使います。

## Project Templateとは

Project Templateという言葉自体は勝手に僕がつけた造語です。
その名の通りProjectのTemplateです。

## Project Templateの作り方

Macの方への説明になってしまいますが、Windowsの方も似たような方法で行けると思います。

まず、「Android Studio.app」を右クリックして「パッケージの内容を表示」を選択します。

<img src="https://qiita-image-store.s3.amazonaws.com/0/47114/75cf20e4-0de0-5fd7-f3d9-a7298ed58849.png" width=400 />

中を開いて「plugins」-> 「android」->「lib」->「templates」->「activities」と潜っていくとここにどこかで見慣れたTemplate一覧があります。

<img src="https://qiita-image-store.s3.amazonaws.com/0/47114/6b5bfb2b-c933-57ef-b1ca-4bb144c54cbe.png" width=700 />

ここにTemplateを追加する事で下記のように自作のTemplateが表示されます。(下記の場合は Blank Activity Kugimiya　がそれです。)

<img src="https://qiita-image-store.s3.amazonaws.com/0/47114/64f0a39c-40b7-96e1-9866-48100f15f6bc.png" width="600" />

ではTemplateの作り方を説明します。
ベースとなるTemplateをコピーして適当にリネームします。
下記では「BlankActivityKugimiya」がそれです。

<img src="https://qiita-image-store.s3.amazonaws.com/0/47114/6b5bfb2b-c933-57ef-b1ca-4bb144c54cbe.png" width=700 />

今回は、root/src/app_package配下とrecipe.xml.ftlのみ触ります。
まず、app_package 配下を下記のような構成にします。

```
app_package
├─ models
|  ├─ SettingModel.java.ftl
|  ├─ package-info-models.java.ftl
|  ├─ entities
|  |   ├─ Setting.java.ftl
|  |   └─ package-info-entities.java.ftl
|  ├─ prefs
|  |   ├─ SettingPrefs.java.ftl
|  |   └─ package-info-prefs.java.ftl
|  ├─ apis
|  |   └─ package-info-apis.java.ftl
|  └─ provider
|      └─ package-info-provider.java.ftl
├─ utils
|   └─ package-info-utils.java.ftl
├─ fragments
|   └─ package-info-fragments.java.ftl
├─ services
|   └─ package-info-services.java.ftl
└─ views
    └─ package-info-views.java.ftl
```

生成したいものはファイル名の最後に「.ftl」を付け加えて、「${packageName}」でapp_packageまでのパッケージ名を取得できるので、つじつまが合うように書きます。

例えば、Setting.java.ftlは

```java:Setting.java.ftl
package ${packageName}.models.entities;

/**
 * Setting Entity
 * @author Kugimiya
 */
public class Setting {
}

```
となり、package-info-models.java.ftlは下記のようになります。

```
/**
 * Models.
 * @author Kugimiya
 */
package ${packageName}.models;
```

(ちなみになぜpackage-info.java.ftlでなくpackage-info-models.java.ftlなどとなっているかというと、名前が被ると全て最初に認識されたものが生成されてしまうからです。)

次に、recipe.xml.ftlを修正します。といっても<!-- ここから --> から　<!-- ここまで --> の部分を挿入するだけです。

```

<?xml version="1.0"?>
<recipe>

    <#if appCompat><dependency mavenUrl="com.android.support:appcompat-v7:${targetApi}.+"/></#if>

    <merge from="AndroidManifest.xml.ftl"
             to="${escapeXmlAttribute(manifestOut)}/AndroidManifest.xml" />

    <instantiate from="res/menu/main.xml.ftl"
            to="${escapeXmlAttribute(resOut)}/menu/${menuName}.xml" />

    <merge from="res/values/strings.xml.ftl"
             to="${escapeXmlAttribute(resOut)}/values/strings.xml" />

    <merge from="res/values/dimens.xml.ftl"
             to="${escapeXmlAttribute(resOut)}/values/dimens.xml" />
    <merge from="res/values-w820dp/dimens.xml"
             to="${escapeXmlAttribute(resOut)}/values-w820dp/dimens.xml" />

    <instantiate from="res/layout/activity_simple.xml.ftl"
                   to="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />

    <instantiate from="src/app_package/SimpleActivity.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />

    <!-- ここから -->

    <instantiate from="src/app_package/models/package-info-models.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/models/package-info.java" />
    <instantiate from="src/app_package/models/entities/package-info-entities.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/models/entities/package-info.java" />
    <instantiate from="src/app_package/models/prefs/package-info-prefs.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/models/prefs/package-info.java" />
    <instantiate from="src/app_package/models/provider/package-info-provider.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/models/provider/package-info-provider.java" />
    <instantiate from="src/app_package/utils/package-info-utils.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/utils/package-info.java" />
    <instantiate from="src/app_package/services/package-info-services.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/services/package-info.java" />
    <instantiate from="src/app_package/fragments/package-info-fragments.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/fragments/package-info.java" />
    <instantiate from="src/app_packag/package-info.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/package-info.java" />

    <instantiate from="src/app_package/models/entities/Setting.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/models/entities/Setting.java" />
    <instantiate from="src/app_package/models/prefs/SettingPrefs.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/models/prefs/SettingPrefs.java" />
    <instantiate from="src/app_package/models/SettingModel.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/models/SettingModel.java" />

    <!-- ここまで -->

    <open file="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
    <open file="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />

</recipe>


```

以上で完了です！

早速新規プロジェクトを立ち上げ自作のテンプレートを生成してみると、しっかり生成されている事が確認できます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/47114/5a58b526-0740-fbdc-74c8-71068b0d2bb3.png" width=400 />

## まとめ

アプリを量産したい方、自分自身のフレームワークが固まっている方、固めたい人は作るべきだと思います。
Project Templateを作って、開発効率を上げましょう！

## バーストリンカーなら合わせて読みたい
・[【Android】もっと先へ「加速」したくはないか、少年 〜File Template編〜](http://qiita.com/kgmyshin/items/6b34c1f576a73c894f72)