Android のライブラリづくりとライセンスについて

こんにちは。ヘルスケア事業部の関口(@tanukiti1987)です。

普段はRailsを使いつつ、おいしい健康というサービスの開発をしているのですが、ご縁があって3ヶ月ほど前からAndroidアプリ開発に携わっています。

今回はそんなAndroid用のライブラリを誰でもお手軽に公開して、Android開発をグイグイ高速化していこう!という観点からお話をしたいと思います。

忙しい人向けの3行まとめ

  • Android向けライブラリを公開するのは、わずか5ステップのみ
  • 公開するライブラリにはきちんとライセンスを書こう
  • ライセンスに特にこだわりがなければ、Apache2.0, MIT あたりがよい

はじめに

iOSとAndroidの開発上の違い

私自身、前職で2年ほどiOSをメインで開発していたということもあり、Androidは機種差分、バージョンの断片化こそあれ、ネイティブアプリ作りの根幹は変わらないだろうと思っていました。

しかしながら、AndroidではiOSとは違い、カメラ周りの制御が相当苦労することに始まり、iOSで用意されているような、例えば UIImageView を角丸にするような処理、 ページングを便利に表現してくれる UIPageControl のUIパーツが無いなど、大きいところから細かいところまで、違いがあるものでした。 (当たり前といえば、当たり前なのですが。。)

痒い所に手が届くライブラリが少ない

ライブラリを探してみるも、自分のプロダクトには不要なコードを含んだ大きなライブラリ。 はたまた、軽い処理のものもちらほら見かけるも、ライセンスが書いてなくて使えない。なんていう経験がしばらく続きました。

なければ作ればいい!

きっと誰かが悩み苦しんだ道だろうけど、その道を通るにはまた同じように悩んだりしないといけないのは、少しモヤモヤするものです。 ぜひこの記事をキッカケにAndroidの開発効率を高めるべく、小さくても十分に使う余地のあるコード をライブラリ化して、公開していきましょう!

ライブラリ化によるメリットは大きい

自分が現在作っているプロダクトの一部のロジックやUIパーツをライブラリ化することで、いくつかのメリットが出てきます。

  • ビジネスロジックを追い出すことで実装はシンプルにわかりやすくなる
  • クラスの責務も明確に
  • 結果、テストも書きやすくなる

誰にでも公開するにあたり、ビジネスロジックは当然含ませることができません。

一つ一つのクラスがビジネスロジックと疎結合になることにより、より実装がシンプルになることが期待できます。

すると、クラスごとの責務がキレイにわけられたり、結果テストもしやすくなる!コードの保守性も良くなる!など、よりよい開発サイクルを回すことができるようになります。

では、そんな期待を込めつつ早速ライブラリを作ってみましょう。

GitHubにライブラリを公開するまでの5ステップ

ここからは 実際にライブラリを作って、GitHubに公開するまでの方法をお伝えしていきます。 今回は試しに、ListViewGridViewScrollView の上に展開した上で設置するパーツを提供するライブラリを公開してみます。

またIDEは、AndroidStudio を使用しての説明になります。

今回、試しに作ったものは https://github.com/tanukiti1987/ExpandedViews に公開しておりますので、ソースファイルの置き場などに困ったときにはご参考ください。

では、早速とりかかってみましょう!

STEP 1. 新しいプロジェクトとモジュールの準備

まずは、おなじみ。プロジェクトを作ります。

f:id:tanukiti1987:20150615163326p:plain

名前は、viewを展開した上で表示するので、ExpandedViews と名づけてみます。 今回はActivityなどは含みませんので、 AddNoActivityで進んで頂いて大丈夫です。

そして、新しいモジュールを追加します。 ここでは、 AndroidLibrary という項を選択し、パッケージ名等を決めていきます。

f:id:tanukiti1987:20150615163459p:plain

f:id:tanukiti1987:20150615163624p:plain

GitHubに公開することを意識しつつ、的確な名前をつけてあげましょう。

STEP 2. モジュール化したいコードを書き進める

めでたく箱が用意出来たので、出来上がったパッケージの下にモジュール化したいコードを書き進めていきます。

今回のViewであれば、こんな感じ。

f:id:tanukiti1987:20150615163628p:plain

通常のプロジェクトで開発しているときと同様、作られたパッケージの下にコードを追加していくイメージです。

STEP 3. AndroidArchive(AAR) をビルドする

ここまで来たら、もうリリース一歩手前。

AARといういわゆるAndroidライブラリの固まりのようなものをビルドします。

AAR についてはこちらに詳しく載っています。

プロジェクトディレクトリ直下で、以下の様なコマンドを叩き、AARを作成します。

$ ./gradlew assembleRelease

しばらく待った後に BUILD SUCCESSFUL が出ればおそらく無事にAARが作成できているはずです。

$ find . -name '*.aar'

などのコマンドを使い、AARができているかを確認してみましょう。

STEP 4. Maven リポジトリを配置する

今回はGitHubをMavenリポジトリとして、ライブラリを使用できるようにしたいため、その形式に合わせたディレクトリ構成でAAR等を配置するスクリプトを 追加したモジュール以下の build.gradle に追記します。

今回であれば、expandedviews/build.gradle になります。

そこで、以下の様なスクリプトを追加します。

## リポジトリのルートディレクトリ名を指定
## 使用するときのURLに影響します
def repo = new File(rootDir, "repository")

apply plugin: "maven"

uploadArchives {
    repositories {
        mavenDeployer {
            repository url: "file://${repo.absolutePath}"
            pom.version = '1.0.0'
            pom.groupId = 'com.tanukiti1987.expandedviews'
            pom.artifactId = 'expandedviews'
        }
    }
}

それぞれの設定項目が示すところはMavenのPOMの生成 を読んでいただくとして、これらの設定は、実際にライブラリを取り込む側のプロジェクトで記述するライブラリの指定方法に影響してきます。

ここで1つ気をつけなければいけないのは、groupId はライブラリのプロジェクト名にすることです。

1つのライブラリプロジェクトには、複数のartifact が含まれるものがあります。

facebook が出している stetho であれば、ライブラリプロジェクトに stetho-okhttp stetho-timber など複数の artcifact が含まれるものもあるため、 groupId は開発者の namespace とイコールではないことに注意してください。

このスクリプトを書き終えたら、プロジェクト直下で以下のコマンドを実行します。

$ ./gradlew uploadArchives

これを行うことで、プロジェクト直下に repository というディレクトリが出来上がり、AARもそれに合わせて配置されます。

STEP 5. GitHubに公開する & 実際に使ってみる

あとは、GitHubにリポジトリを作り、pushするだけです。

pushが完了した時点で、このライブラリを使用したいプロジェクトは、各 gradle.build ファイルにおなじみの以下の記述を追加するだけで、使えるようになります。

repositories {
    maven { url 'http://raw.github.com/tanukiti1987/ExpandedViews/master/repository/' }
}

dependencies {
    compile 'com.tanukiti1987.expandedviews:expandedviews:1.0.0'
}

この dependencies 以下に追記する記述が、先ほどの mavenDeployer での設定に関係してきますので、ここをイメージしながら、groupIdやartifactIdを決めるのが良いかも知れません。

この記述をした後に、プロジェクトでビルドを行えば、めでたく自分のアプリケーション内で使えるようになります。

f:id:tanukiti1987:20150615163635p:plain

ここまででひとまずライブラリを公開する手順でした。文章で表現すると長かったものの、実際に作業するとそれほど時間がかからないことにお気づきになるかと思います。

忘れちゃいけないライセンス表記

ライブラリ公開の記事もこれでおしまい!と思ってしまいそうですが、公開して誰もが使えるようにするにはもうひとつ大事な作業があります。

そうです、ライセンスの表記です!

ライセンスを書かないとデフォルトのライセンスが適用される

もし、ライセンスを書かずにGitHub等で公開したコードは、公開者自身が全ての著作権を持つ、All rights reserved なライセンスが適用されます。

これは、私的利用については問わないが、ソフトウェアの複製、改変、再頒布は行えないことを意味します。

iOSやAndroidに関しては、ライブラリのロジックをアプリに載せた上で、クライアントにアプリを配布します。

この場合、ソフトウェアの再頒布にあたる可能性が出てきてしまい、アプリでそのライブラリを使用するのが難しくなってくることが考えられます。(利用許可を作者に直接取れば、別の話ですが。)

こうなってくると、気軽な気持ちでそのライブラリは使えず、せっかくライブラリを公開している意義を失ってしまいます。

Android では Apache2.0 ライセンスがよく使われる

Androidで著名なライブラリは、だいたいがApache2.0のライセンスが使われています。

これは、Googleの AndroidOpenSourceProjectがそれを選んでいるところが大きいと思われます。

Android is about freedom and choice. The purpose of Android is promote 
openness in the mobile world, and we don't believe it's possible 
to predict or dictate all the uses to which people will want to put our software.

http://source.android.com/source/licenses.html

このページにもあるように、Androidはモバイル環境でのオープンさを推進させ、全ての人々がAndroidのソフトウェアを使いたくなる世界が来ることを期待している。(意訳)とあります。

しかし、なぜMTIやBSDライセンスなども、Apache2.0 と親しいライセンスではありますが、親しいだけに1つに統一するという意を込めて、このページではApache2.0を選んでいるものと思われます。

MITライセンスで、ゆるく公開してみる

とは言え、個人でライブラリを公開するときには Apache2.0にも近く、更にゆるいMITライセンスを選択するのも手でしょう。

MITライセンスでは、作者の名前を記すことと、作者に一切の責任を求めないことを明記しています。

Apache2.0とMITが大きく異るのは、作者から利用者への特許権の許可を明確にしているところです。

このことから、どちらを選択しても大きく内容は異ならないことから、個人での小さなライブラリについてはMITでもよいと思っています。

ライセンスをお手軽に追加する方法

そんな背景を理解しつつ、自分のライブラリにもライセンスを追加していきます。

この記事では、2つの方法のいずれかでライセンス表記をすることをおすすめします。

1. Choose a license を使用してみる

先ほどのAndroidOpenSourceProjectの思想に沿うのであれば、Apache2.0 を使えば良いのですが、少しこだわってライセンスを選びたい。どんな種類のライセンスがあるか知りたい。といった時におすすめです。

このサイトでは、どういったマインドでライブラリを公開したいかを選べば、それ相当のライセンスが表示されます。 表示されたライセンス中にある 著作者 を書き換えるだけで立派にライセンスとして成立します。

2. GitHubのリポジトリ作成時にライセンスを選んでしまう

私も最近知ったのですが、リポジトリを作るときにライセンスを選べば自動でそのライセンスのREADME.mdをつくってくれる機能がGitHubにあります。

f:id:tanukiti1987:20150615163632p:plain

その機能を使い、ライセンスを追加してしまうのもひとつの手です。

合わせて覚えておきたい

お世話になったライブラリを列挙する

私が今作っているアプリや他のアプリでもそうですが、ネイティブアプリにはライセンス画面(ページ)が存在しているものが多いです。

アプリの制作の途中で、ライセンスページを作っていると、様々なライブラリにお世話になった実感が湧いてくるものです。

それがありがたいという思いと共に、様々な人達に助けられて出来上がったアプリなのだと感慨深い気持ちになったりします。

ぜひ、皆さんが作る商用アプリはもちろん、個人アプリでも、ライセンス表記の義務のあるライブラリを使用した際には、ライセンス表記のページを作ってみてください。

自分(たち)のプロダクトが色々なライブラリに支えられてできたことを知ると、よりプロダクトに対して愛着が湧いたりしてくるのでオススメです。

自分のライブラリを使ってもらう喜びを感じてみる

また、自分が作ったライブラリがどこかのアプリに使われていることを知ったら、きっと嬉しくなることでしょう。

たとえ小さくてもライブラリをバシバシ公開してき、Android開発者同士がより高速に開発できる日を目指していきましょう!

おわりに

今回は、手軽にライブラリを公開できる方法をご紹介しました。

この方法でライブラリの公開を行うと、作者は簡単に公開できるものの、利用者では build.gradlerepositorydependencies の二箇所にライブラリ使用のための追記を行わなくては行けません。

もし、たくさん使われるようなライブラリに成長した場合、または最初から利用者にも手軽に使えることを目指す場合には jcenter に登録する方法があります。

jcenter での公開になると、アカウントの登録であったり公開までのハードルが今回ご紹介した方法よりはハードルがあるため、割愛させていただきました。

まずは、気軽に!というところでまとめとさせていただきます。

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/