外部
ライブラリーの
利用
と
作成
著:八木俊広
17
・ライブラリーとは何か ・ライブラリーがなぜ必要か ・Androidで利用できるライブラリーの種類 ・Androidでライブラリーを利用する方法(jar)
この節で出てくるキーワード一覧
ライブラリー jar ライブラリープロジェクト aar so 静的リンク 動的リンク 参照 クラスパス クラスファイルこの章に出てくるライブラリー、クラス一覧
android-http-async (https://github.com/loopj/android-async-http)外部ライブラリーを
使ってみよう
17-1
著:八木俊広この節で学ぶこと
外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章 ライブラリーとは、特定の処理を行うプログラムをひとまとめにし、他のプログラムか ら利用できる形式にしたモノのことです。ライブラリーは再利用のための仕組みだと 言い換えてもよいでしょう。例えば画像処理や数値計算などの汎用的な処理を行う プログラムをライブラリーにすることで、他のプログラムからその機能を自由に利用で き、一度開発したプログラムを再度使いまわせるようになります(図1)。 複数のライブラリーを組み合わせてより高機能なプログラムを作成し、それをまた ライブラリーにするといったことも可能です。 Android自身も画像処理や音声処理や様々な部分でライブラリーを利用してい ます。また、Androidアプリケーションを開発する際に利用するAndroid SDKもライ ブラリーです。Androidが提供するライブラリーによって私達はアプリケーションを開 発することができるのです。Androidに限らず、現代の様々なプラットフォームやプロ ダクトは、過去に開発されたライブラリーの積み重ねによって成り立っていると言って も過言ではありません。 ライブラリーは、利用するOSやCPUやプログラミング言語などによって、様々な形 式に分かれています。Androidアプリケーションで利用できるライブラリーの形式は 「jar」(Java Archive)、「ライブラリープロジェクト」、「aar」(Android Archi
ve)、「so」(Shared Object)の4種類です。以下、順に見ていきましょう。
図1:アプリケーションとライブラリーの関係のイメージ
ライブラリーとは何か
17 -1-1
Android アプリケーションおけるライブラリー
jar(Java Archive)
Androidアプリケーションは基本的にJavaでソースコードを記述します。そのた め既存のJavaライブラリーの多くを利用できます。Javaライブラリーの形式は「jar」 (Java Archive)と呼ばれ、クラスファイル群と署名やバージョン等のメタ情報が 書かれたファイルなどがアーカイブされています。 Java Archive(JAR)Featuresについて詳しくは、http://www.cse.yorku. ca/tech/other/jdk1.2.1/docs/guide/jar/を参照してください。 コンパイル時に「jar」ファイルをクラスパスに通すことで利用できます。Androidア プリケーションの場合は、プロジェクトの「libs」ディレクトリに「jar」ファイルを配置す るだけで自動的にパスが通り、利用が可能となります。 自動的にパスが通るのは、Eclipse+ADTプラグインの環境を用いた場合です。 Android Studioの場合は「build.gradle」に「jar」ファイルの参照を記述しま す。ライブラリープロジェクト
「ライブラリープロジェクト」は、Androidアプリケーション専用のライブラリー形式 です。通常のアプリケーションと同ようにプロジェクト形式で開発を行います。ライブラ リープロジェクトにはソースコードの他にレイアウトXMLや画像等のリソースファイル を含めることができます。これにより、画面を含んだUIやスタイル、画像リソースなどを アプリケーションから参照して利用できるようになります。aar(Android Archive)
「aar」はライブラリープロジェクトをアーカイブした形式です。2013年のGoogle I/Oで「Android Studio」という新しいIDEが発表されました。Android Studio は「Gradle」というビルドツールと強く統合されており、Gradleを通してアプリケー ションをビルドする形になっています。Gradleからライブラリープロジェクトを参照する 時に利用するのがこの「aar」形式です。so(Shared Object)
Androidのアプリケーション開発では、「NDK」を用いることで、C/C++を使っ てプログラムを記述できます。Android NDK(Native Development Kit)はAndroidアプリケーションで 利用するプログラムの一部、あるいは全体をC/C++で開発するための開発環境
外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章 です。 NDKを使ってビルドを行うと「so」ファイルを出力し、「apk」に同梱します。Andr oidアプリケーションから「so」ファイルへは「JNI」(Java Native Interface)を通 してアクセスすることになります。 ライブラリーは、ソースコード、オブジェクトコード、専用のフォーマットなど、さまざま な形式で提供されており、利用するプログラムはそれらの形式に合わせてライブラ リーと結びつく必要があります。ライブラリーと結びつく方式は大きく分けると「静的リ ンク」と「動的リンク」に分類できます。
静的リンク
静的リンクはアプリケーションとライブラリーをコンパイルのリンク時に結びつけ、実 行ファイルに含める方式です。静的リンクの場合、リンク時にライブラリーのAPIや バージョン等の整合性をチェックすることになるので、コンパイルの時点で問題があ れば検出できます。ただし、実行ファイルにライブラリーファイルを含めるので、実行 ファイルのサイズは大きくなってしまいます。また、ライブラリーをアップデートするには、 再度アプリケーションをコンパイルし直す必要があります。Androidにおいては「ライ ブラリープロジェクト」や「aar」、「exportedなjar」が、静的リンクによって結びつく ライブラリーです(図2)。 図2:静的リンクのイメージ静的リンクと動的リンク
17 -1-3
動的リンク
動的リンクはアプリケーションを実行する時にライブラリーとリンクする方式です。 Windowsを利用している方は「.dll(Dynamic Link Library)」という拡張 子のファイルを見たことがあると思います。これが動的リンクができるライブラリーです。 実行ファイルとは独立したファイルなので、実行ファイルのサイズを圧迫することが ありません。また複数のアプリケーションから同時に利用したり、ファイルを差し替えれ ば、再コンパイルすることなくライブラリーをアップデートしたりできます(図3)。しかしラ イブラリーが互換性のないアップデートをしてしまった場合には、動作時にエラーと なってしまいます。そのため、動的リンク形式のライブラリーを利用する場合は、バー ジョン管理が重要になります。Androidでは、Android SDKや「so」ファイルが動 的リンク形式のライブラリーとなります。 「exportedなjar」ファイルは静的リンク 通常「jar」ファイルは動的リンク形式のライブラリーです。しかしAndroidアプリケー ションは「Dalvik VM」というJavaとは異なる仮想マシン上で動作します。このため、 「class」ファイルを「Dalvik VM」用の「dex」ファイルに変換する際に、参照している 「jar」ファイルの中身も「dex」ファイルに変換し、アプリケーションに組み込みます。コ ンパイルのタイミングでアプリケーション内にライブラリーを組み込んでいるので、An droidアプリケーションでは「jar」ファイルを静的リンクしているということになります。 「exportedなjar」とは「dex」ファイルに変換する対象に含める「jar」ファイルのことを指 します。例えば「android.jar」はexportedではないので、コンパイル時には処理されま せん。アプリケーションを実行する時に動的にリンクします。
check!
図3:動的リンクのイメージ外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章 例えば最新のAndroidのAPIを使ったアプリケーションを、古いAndroidが搭 載された端末で動作させるとエラーが発生します。これは動的リンクによってAndr oid SDKとアプリケーションが結びついているからです。古いAndroidに存在しな いAPIを利用していたりすると、当然APIが見つからないのでエラーとなるのです。 前述の通りAndroid SDKもライブラリーです。しかしAndroidアプリケーション を開発する時に「Android SDKのライブラリーを使っている」と意識したことはあま りないかもしれません。ただ、実は新規プロジェクトを作成する時にAndroid SDK のライブラリーを選択しています(図4)。 新規プロジェクトを作成する際のウィザードで選択する「Compile With」は、ど のバージョンのAndroid SDKを使ってプロジェクトをコンパイルをするか設定する 項目です。この設定に従って、Androidプロジェクトに「android.jar」ファイルへの 参照が追加されます。「android.jar」ファイルがAndroid SDKの実体であり、そ の中に含まれているActivityクラスやTextViewクラスなどを使ってアプリケーショ ンを作ることになります。 EclipseでAndroidプロジェクトの「Package Explorer」を見てみると、参照し ているAndroid SDKのバージョンや中身を確認できます。図5は、Android 4.4.2 の「android.jar」を参照している例です。ライブラリーの中にどのようなクラスがある か確認できます。 図4:新規プロジェクトのウィザード
Android SDK もライブラリー
17 -1-4
クラスを開くとソースコードを見ることもできます。図6は、Activityクラスのソース コードを開いた例です。Activityクラスがどのように実装されているか読むことがで きます。普段よく使う「setContentView」メソッドや「findViewById」メソッドがど のように実装されているか是非一度読んでみてください。 図5:Android 4.4.2の「android.jar」参照例 Androidプロジェクトで参照しているAndroid SDKには膨大な数のクラスが含まれている。そのクラスが持つメソッ ドを見ることもできる 図6:Activityクラスのソースコードを覗く
外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章 クラスを開いてもソースコードが見られない場合は、Android SDKのソースコー ドをインストールしているか確認してください。図7のように、「Android SDK Mana ger」を使って、該当するAndroidバージョンのソースコードがインストールされてい るか確認できます。 ライブラリーの形態とAndroidアプリケーションにおけるライブラリーの種類がわ かったところで、さっそくライブラリーを使ってみましょう。本項では「android-async-http」(https://github.com/loopj/android-async-http)という非同期通信 のためのオープンソースライブラリー使って、ネットワークプログラミングの章(14-2-5 「HttpURLConnectionの利用」)で作った「HttpURLConnection」の処理を 置き換えます。「android-async-http」は、さまざまな形式で配布していますが、ここ では「jar」ファイルを直接利用することとします。 オープンソースとは、プログラムのソースコードを第三者に公開していることを表しま すが、実際にはもう少し立て込んでいます。ソースコードの複製、改変、再頒布など の条件を定めたオープンソースライセンスを持つプログラムをオープンソースソフトウェ アといいます。「android-http-async」の場合は「Apache License, Version 2.0」というライセンスを採用しています。オープンソースソフトウェアの利用者はオープ ンソースライセンスに従う必要があります。
図7:Android SDKのソースを「Android SDK Manager」で確認し、必要に応じてダウンロードする
jar 形式のライブラリーを使ってみよう
jarファイルをダウンロードし、libsディレクトリーへコピーする
「android-async-http」の「jar」ファイルは「http://loopj.com/android- async-http/」でダウンロードできます。本書の執筆時点では「android-async-http-1.4.6.jar」をダウンロードできました(図8)。 ダウンロードした「jar」ファイルをAndroidプロジェクトの「libs」ディレクトリーにコ ピーすれば利用できます(図9)。 図8:「android-http-async」の「jar」ファイルをダウンロードする 図9:「jar」ファイルを「libs」ディレクトリーにコピーする外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章 通信処理を行うので「AndroidManifest.xml」への「android.permission. INTERNET」パーミッションの追加も忘れずに行いましょう(リスト1)。
動作チェック
正しく導入ができたか確認してみましょう。新しく作ったプロジェクトの「MainAct ivity.java」の冒頭にリスト2に示す「import」文を記述し、エラーが発生しなけ れば準備完了です。 もしエラーになる場合は、「jar」ファイルをコピーした場所が正しいかどうかを確認 したり、プロジェクトを一度「clean」するなどしてみてください。ライブラリーを用いない場合のコードをおさらい
「android-async-http」を使う前に、まずはライブラリーを使わない場合のコード をおさらいしてみましょう。リスト3は、ネットワークプログラミングの章で実装した「Ht tpURLConnection」を用いるコードから、一部のログ出力を取り除いたものです。 接続の準備やデータの取得、後処理などたくさんの処理を記述しています。また、 このコードはUIスレッドでは実行できないため、「AsyncTask」等を用いて別のス レッドで呼び出す仕組みを実装しています。 リスト1:AndroidManifest.xml(android.permission.INTERNET"パーミッションを追加する) <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="省略" > <uses-permission android:name="android.permission.INTERNET"/> <application> <!-- 省略 --> </application> </manifest> //} リスト2:MainActivity.java(導入したライブラリーのクラスをインポートする) import com.loopj.android.http.AsyncHttpClient;リスト3:MainActivity.java(HttpURLConnectionを用いる場合)
public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); new DownloadTask().execute();
}
private static class DownloadTask extends AsyncTask<Void, Void, Void> { @Override
protected Void doInBackground(Void... params) { try {
URL url = new URL("http://tomorrowkey.github.io");
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET");
connection.setRequestProperty("Host", "tomorrowkey.github.io"); connection.connect();
int responseCode = connection.getResponseCode(); Log.d("TEST", "Response-Code=" + responseCode);
String contentLength = connection.getHeaderField("Content-Length"); Log.d("TEST", "Content-Length=" + contentLength);
String contentType = connection.getHeaderField("Content-Type"); Log.d("TEST", "Content-Type=" + contentType);
InputStream inputStream = connection.getInputStream(); String body = readToEnd(inputStream);
Log.d("TEST", "body=" + body); inputStream.close();
} catch (MalformedURLException e) { throw new RuntimeException(e); } catch (IOException e) {
throw new RuntimeException(e); }
return null; }
private String readToEnd(InputStream inputStream) throws IOException { StringBuilder sb = new StringBuilder();
int length;
byte[] buffer = new byte[1024];
while ((length = inputStream.read(buffer)) != -1) { sb.append(new String(buffer, 0, length));
}
return sb.toString(); }
} }
外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章 「Socket」を使った通信処理に比べれば、「HttpURLConnection」でもかな り楽に通信処理を記述できるようになっています。しかしまだまだ冗長です。Andro odアプリケーションで「HttpURLConnection」を使って通信処理をする場合に は、常に以下のことを考慮しなければなりません。 ・ AsyncTaskなど非同期処理のコードを追加しなければならない ・ 通信の成功や失敗を自分でチェックしなければならない ・ レスポンスをInputStreamで処理しなければならない もちろんこれらの約束ごとは、一度覚えてしまえば、それほど難しいものではないで しょう。しかし、アプリケーションで通信処理をする場合、いつも実装しなければならな いため、「ボイラープレート・コード」を沢山書くことになります。 ボイラープレートとは鋳型のことです。ボイラープレート・コードは決まりきっているけ ど省略できないコードの断片のことを表します。 ボイラープレート・コードが増えると、本来やりたいことに割くべき時間が削られてい きます。通信処理の場合、やりたいことは通信処理そのものではなく、通信の結果 取得したデータを取り扱うことのはずです。ボイラープレート・コードを回避するには、 それらを簡単かつ汎用的に再利用できる仕組みを用意すればよいわけですが、大 抵の場合時間がかかります。そういった場合にライブラリーの力を借りることになるわ けです。
android-async-httpを用いたコード
では「android-async-http」を利用してみましょう。「android-async-http」は 非同期的にネットワーク処理を行う「AsyncHttpClient」クラスと、同期的にネット ワーク処理を行う「SyncHttpClient」クラスを提供しています。今回行いたいの は非同期通信なので、「AsyncHttpClient」クラスを利用します。 リスト4は、「AsyncHttpClient」クラスを使って実際に非同期のリクエスト処 理する例です。実装の詳細はここでは深く立ち入りませんが、「HttpURLConnec tion」を使う例に比べて簡潔にリクエスト処理を記述できていることが分かると思いま す。 boilerplateは正確には鋳型(鋳型 は強いて言えばtemplate)ではあり ませんが、boilerplate(ボイラーを作 るための板、または機械の銘版)が、 コンピューター用語としてこのような 意味に使われるのかはよく分かりませ ん...「AsyncHttpClient」クラスは自動的に非同期でネットワーク処理を行うので、UIス レッドから呼び出しても問題ありません。また通信処理の結果を受け取るための「Asyn cHttpResponseHandler」クラスの「onSuccess」メソッドや、「onFailure」メソッドは 自動的にUIスレッドで呼び出されるのでスレッドを意識しなくてもすみます。
ライブラリーの使い方を知るには
大抵のライブラリーには「説明書」があります。「android-http-async」の場合 は以下のページを参照するとよいでしょう。 概要と使い方: http://loopj.com/android-async-http/ javadoc: http://loopj.com/android-async-http/doc/com/loopj/ android/http/package-summary.html 「android-http-async」はオープンソースのライブラリーですので、ソースコード そのものを参照するという手もあります。「android-http-async」のソースコードは リスト4:MainActivity.java(android-http-asyncを用いる場合)public class extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); loadAsync();
}
private void loadAsync() {
AsyncHttpClient client = new AsyncHttpClient(); //自動的に別のスレッドで実行する
client.get("http://tomorrowkey.github.io", new AsyncHttpResponseHandler() { @Override
public void onSuccess(int responseCode, Header[] headers, byte[] response) { //通信処理が終了するとUIスレッドで呼び出される
String body = new String(response); Log.d("TEST", "body=" + body); }
@Override
public void onFailure(int responseCode, Header[] headers, byte[] response, Throwable e) { //省略
} }); }
外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章 Githubにホスティングされています。 Github: https://github.com/loopj/android-async-http 今回利用した「AsyncHttpClient」クラスのソースコードは以下のURLで読め ます。 AsyncHttpClientクラス: https://github.com/loopj/android-async-http/blob/master/library/src/main/java/com/loopj/andro id/http/AsyncHttpClient.java#L831 リスト4に示したコードでは、「loadAsync」メソッドに通信先のURLが埋め込 まれていました。また、通信結果はログに出力するだけです。これでは通信先を変更 したい場合毎回「loadAsync」メソッドを書き換えなければなりません。いろいろなと ころで再利用ができるよう、以下の条件を満たすように書き換えてみましょう。 1:任意に通信先のURLを変更できる 2:通信結果をStringで受け取って自由に処理できる
任意に通信先のURLを変更できる
リスト4の「loadAsync」メソッドは、通信先URLがメソッド内に書かれているた め「loadAsync」メソッドの外からURLの変更ができません。通信先のURLを引 数で受け取る形にすれば任意のURLを指定できるようになります(リスト5)。 引数を追加することで任意のURLを受け取ることができるようになりました。しかし実 はリスト5の実装ではまだ不十分です。引数「url」が「null」の場合「NullPointer Exception」が発生してしまいます。引数の妥当性をチェックする必要があります。 Androidには「TextUtils」クラスという文字列の操作やチェックができる便利 リスト5:MainActivity.java(loadAsyncメソッドで任意のURLを引数に取る)private void loadAsync(String url) {
AsyncHttpClient client = new AsyncHttpClient(); client.get(url, new AsyncHttpResponseHandler() { //省略 }); }
プログラムの再利用性を高める
17 -1-6
なクラスがあります。「TextUtils」クラスの「isEmpty」メソッドを使えば引数が空 (長さが0)あるいは「null」かどうかをチェックできます(リスト6)。 空、「null」だけでなく、URLとして正しい形式かチェックしたい場合もあるかもし れません。ただ、「AsyncHttpClient」の場合、誤ったURL形式を渡すと「Asy ncHttpResponseHandler」クラスの「onFailure」メソッドが呼び出されるので、 事前チェックが必須というわけではありません。 「String」クラスの「startsWith」メソッドを使えば、指定した文字列で始まってい るかどうかをチェックできます(リスト7)。 もっと手っ取り早く確認するために、「URL」クラスを用いるという手もあります。 「URL」クラスはコンストラクタに渡されたURLが正しいかをチェックし、問題があれ ば「MalformedURLException」をthrowします。チェックはプロトコルとポート番 号に対して行われます(リスト8)。 デフォルトでは、http、https、ftp、file、jarの各プロトコルに該当するかどうかと、 ポート番号が-1以上であることをチェックします。(参考:http://docs.oracle.com/ javase/jp/6/api/java/net/URL.html) リスト6:MainActivity.java(引数の妥当性をチェックする)
private void loadAsync(String url) { if (TextUtils.isEmpty(url)) { return;
}
AsyncHttpClient client = new AsyncHttpClient(); client.get(url, new AsyncHttpResponseHandler() { //省略 }); } リスト7:MainActivity.java(startsWithメソッドを使う) // "http://"で始まっていなかったらreturn if(!url.startsWith("http://")){ return; } リスト8:MainActivity.java(「URL」クラスを使う) try{
URL url = new URL(urlString); }catch(MalformedURLException e){
// URLクラスがMalformedURLExceptionをthrowしたらreturn return;
外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章
通信結果をStringで受け取って自由に処理できるようにする
通信結果をメソッドの呼び出し元に渡すにはどのようにすればよいでしょうか。よく ある誤りをリスト9に示します。何が間違っているかわかるでしょうか。 ここでは、「loadAsync」メソッドの戻り値を「String」にして、通信結果を「retu rn body」で返しています。一見よさそうに思えるのですが実際は誤りです。まず、そ もそもこのコードはコンパイルが通りません。 「AsyncHttpClient」クラスの「get」メソッドは非同期で通信処理を行うので、 「get」メソッドそのものはすぐに終了します。「get」メソッドが終了すると、次に処理す るものはないので「loadAsync」メソッドが終了します。「AsyncHttpResponseH andler」クラスの「onSuccess」メソッドは通信が終わった時呼び出されるので、そ れぞれの処理はリスト10に示した順番で実行されることになります。 リスト9:MainActivity.java(間違った例)private String loadAsync(String url) {
AsyncHttpClient client = new AsyncHttpClient(); client.get(url, new AsyncHttpResponseHandler() { @Override
public void onSuccess(int responseCode, Header[] headers, byte[] response) {
String body = new String(response); return body; } //省略 }); } リスト10:MainActivity.java(処理が実行されるタイミング)
private String loadAsync(String url) {
AsyncHttpClient client = new AsyncHttpClient();
//1 getメソッドを実行する。非同期処理を開始するだけなのですぐ終わる。 client.get(url, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int responseCode, Header[] headers, byte[] response) {
//3 通信処理が終わったら呼び出される String body = new String(response); return body; } //省略 }); //2 loadAsyncメソッドが終了する }
「loadAsync」メソッドは、「String」を戻り値としているので「2」の時点でなんら かの値を返さなければなりません。しかし通信処理はまだ終わっていないため、通 信結果をこのタイミングで返すことはできません。コンパイルを通すためには「return null」といった記述をすることになります。これでは「String」を戻り値にしている意味 がありませんね。 次に「3」のタイミングで「return body」と書いていますが、処理を書いている場 所は、「AsyncHttpResponseHandler」クラスの「onSuccess」メソッドの中で す。「onSuccess」メソッドは戻り値が「void」なので「String」を返すことはできま せん。また、返せたとしても「loadAsync」メソッドの戻り値とはならないので、これもま た意味がありません。 ではどのようにすれば良いか。実はすでに答えがコード中に書かれています。コー ルバックを利用すればよいのです。「AsyncHttpClient」クラスの「get」メソッドは、 「AsyncHttpResponseHandler」クラスを渡してコールバックを受け取るスタイル になっています。同様の仕組みを「loadAsync」メソッドに実装すればよいわけで す。リスト11はコールバックを利用する実装の例です。 リスト12は、URLとコールバック用のinterfaceを引数に取るようになった「loa dAsync」メソッドを利用する例です。これで色々なところから利用できるようになりま した。また、「android-http-async」を利用する部分を「loadAsync」メソッドの中 に隠蔽したことによって、利用する時のコードがシンプルになりました。 リスト11:MainActivity.java(コールバックを利用する) //コールバックを受け取るためのinterfaceを定義する public interface OnLoadListener {
public void onLoad(String result); }
//OnLoadListenerを引数に受け取る
private void loadAsync(String url, final OnLoadListener listener) { AsyncHttpClient client = new AsyncHttpClient();
client.get(url, new AsyncHttpResponseHandler() { @Override
public void onSuccess(int responseCode, Header[] headers, byte[] response) {
String body = new String(response); //コールバックする listener.onLoad(body); } //省略 }); }
外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章 1.RSSフィードを読み込んで結果をTextViewに表示してみよう まず「http://headlines.yahoo.co.jp/rss/list」のページから好きなRSSフィー ドを選んでください。 2.RSSフィードからitem要素を取り出してみよう
「jsoup」(http://jsoup.org/)という「jar」形式のライブラリーを導入し、RSS フィードのitem要素を取り出してみましょう。その後以下の処理を実装してみましょ う。 ・ RSSフィードのitem要素をListViewに表示 ・ ListViewに表示したitem要素をタップして、ブラウザでURLを開く (URLをブラウザで開く方法については、第6章「6-3-2:暗黙的Intent」の項が 参考になるでしょう) リスト12:MainActivity.java(コールバックを渡して結果を受け取る) @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_android_http_async);
loadAsync("http://tomorrowkey.github.io", new OnLoadListener() { @Override
public void onLoad(String result) { //処理 } }); } コードがシンプルになると新たな問題も リスト11、12では、コードがシンプルになりましたが、同時に新たな問題を生んでい る点についても意識する必要があります。「loadAsync」メソッドは通信エラー時の処理 ができません。またヘッダやステータスコードを見ることもできません。シンプルになっ た代わりに制約も生んでいるのです。この制約をどのように取り扱うかはプログラムの 要件によって変わります。今回は細かなハンドリングは意識しないので、この形にして います。
check!
演習問題
まとめ
本節ではライブラリーとは何か、Androidで利用できるライブラリーの種類、 「jar」形式のライブラリーの使い方を学びました。ライブラリーを用いることで効率的 に開発が行えることを体験できたのではないかと思います。 本節では通信処理に関するライブラリーを利用しましたが、他にも様々な種類の ライブラリーがあります。どのようなライブラリーがあり、どういった性質を持っているか を知ることはアプリケーションの開発効率に大きく影響を与えます。不要な開発を減 らせるだけでなく、先人が通った道を見本にして、さらなる改善ができるからです。ラ イブラリーをただ利用するだけでなく、ソースコードを読んだり、ドキュメントを読んだり して「何故そのような実装になっているか」、「何故そのような設計になっているか」を 日頃から考えるようにしてみましょう。外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章 ・ライブラリープロジェクトの生い立ち ・ライブラリープロジェクトの使い方 ・ライブラリープロジェクトのソースを読む ・カスタム属性について ・オープンソースライセンスについて
この節で出てくるキーワード一覧
R.java aidl aapt dex apkbuilder jarsigner zipalign カスタム属性この章に出てくるライブラリー、クラス一覧
Android-Bootstrap (https://github.com/Bearded-Hen/Android-Bootstrap)ライブラリープロジェクトを
使ってみよう
17-2
著:八木俊広この節で学ぶこと
オープンソースライセンス GNU General Public License Apache license 2.0「ライブラリープロジェクト」はAndroid専用のライブラリー形式です。ソースコード とリソースファイルを内部に持つことができ、レイアウトファイルやdrawableを利用する ActivityやViewなどをライブラリーとして提供できます(図10)。 なぜ「ライブラリープロジェクト」が誕生したのでしょうか。「JAR」形式のライブラ リーにリソースファイルを含めることはできないのでしょうか。これらの疑問に答えるに は、Androidアプリケーションがどのようなプロセスでビルドされているかを知る必要 があります。
図11は、「Android Developers」の「Building and Running」に記載さ れているAndroidアプリケーションをビルドするフローです。
詳細はhttps://developer.android.com/tools/building/index.htmlで 確認できます。
Androidプロジェクトから「apk」に変換されるまでの間に複数のツールで順番 に処理されていることがわかります。
これらのツールは$ANDROID_SDK/build-tools/(build tool version)/の 中にあります。 以下、それぞれのツールで何が行われているか見て行きましょう。 図10: JAR形式とライブラリープロジェクト形式の違い
ライブラリープロジェクトとは何か
17 -2 -1
Android アプリケーションのビルドフロー
17 -2 -2
外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章
aidl
「AIDL」は「Android Interface Definition Language」の略で、プロセス 間通信のためのインタフェースを定義する「DSL」です。異なるプロセスで動作する Serviceに対してActivityなどから接続する際に利用します。 「DSL」は「Domain-Specific Language」の略でドメイン固有言語と呼びま す。「DS L」は特定のタスク向けに設計された独自の言語のことを差します。 「AIDL」はプロセス間通信のために設計された独自の言語ということになります。 典型的な例としてはアプリ内課金などを実装する際に「AIDL」を利用します。ア プリ内課金は「Google Play」を通して行います。「Google Play」に対して決済 の処理などを依頼するために「AIDL」を使って接続します。
「AIDL」は、Javaとは異なる独自の言語ですので、そのままではJavaコンパイラ でコンパイルできません。アプリケーションのソースコードをコンパイルする前に、 「AIDL」をコンパイルしてJavaのソースコードを生成します。
aapt
「aapt」(Android Asset Packaging Tool)はアプリケーションのリソースファ イルや「AndroidManifest.xml」を解析し「R.java」を生成します。ここで生成す る「R.java」を使って画像やレイアウトファイルへプログラムからアクセスすることになり ます。その他「values」ディレクトリをコンパイルしてアーカイブします。
Java Compiler
通常のJava言語のコンパイラ(javac)です。「aidl」や「aapt」が生成したソー スコードと、アプリケーションのソースコードをまとめてコンパイルして「class」ファイルを 出力します。dex
「class」ファイルをコンパイルし、「Dalvik VM」のバイトコードである「dex」ファ イルへ変換します。この時、Androidプロジェクトが「JAR」形式のライブラリーを利 用している場合は、それらのライブラリー内の「class」ファイルも同時に「dex」ファイ ルへコンパイルします。
apkbuilder(sdklib.jar)
「dex」ファイル、コンパイルしたリソース、画像類などのリソースファイルをアーカイブ して「apk」ファイルを作成します。外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章
jarsigner
「jarsigner」はJavaの標準のツールです。「jarsigner」を使って「apk」ファイ ルにデジタル署名を行います。デバッグビルドの時はデバッグ用の共有の署名が使 われますが、アプリケーションをリリースする場合は自分で証明書を作成する必要が あります。zipalign
「zipalign」は「apk」を最適化するツールです。「apk」はアプリケーションのイン ストール時や、ホームアプリケーションに名前やアイコンを表示する時など様々な場面 で読み取られます。「apkbuilder」でアーカイブした「apk」の内部を「zipalign」 を使って整列することで、「apk」の読み取りを高速化できるようになります。 Androidアプリケーションのビルドフローを見ると、「JAR」形式のライブラリーが 処理されるのは「dex」ファイルに変換されるタイミングだということがわかります。リソー スファイルを取り扱うには「R.java」に定義されたリソースIDが必要です。「R.java」 は「aapt」コマンドによって生成されるので、「JAR」形式のライブラリーからは「R.j ava」の中のリソースIDを事前に知ることができません。そのため「JAR」形式のライ ブラリーではリソースファイルを持てない、持ったとしても内部から利用できない、という ことになるわけです。ライブラリープロジェクトの誕生
そこで誕生したのが「ライブラリープロジェクト」です。「ライブラリープロジェクト」は Androidプロジェクトと同じ構造なので、リソースファイルを持てます。ビルドの際は Androidプロジェクトと一緒にビルドフローを辿るので、「R.java」が問題になること はありません。この仕組みによって、画面を持つActivityやViewなどをライブラリー 化できるようになりました。JAR 形式のライブラリーがリソースファイルを持てない理由
17 -2 -3
「ライブラリープロジェクト」を使ってアプリケーションを開発してみましょう。本節で は「Android-Bootstrap」というスタイリッシュなUIの構築を助けるライブラリーを 導入します。
Android-Bootstrapとは
「Android-Bootstrap」は、Web用のフロントエンドフレームワーク「Bootstr ap」のコンセプトを元に構成したAndroid用のUIライブラリーです。角丸ボタンや アイコン付きボタン、「FontAwesome」の利用、円形サムネイルなど、様々なUI部 品を提供しています(図12)。ライブラリープロジェクトをダウンロードする
「Android-Bootstrap」は「https://github.com/Bearded-Hen/ Android-Bootstrap/」からダウンロードできます。画面右下の「Download ZIP」からプロジェクト全体をダウンロードしてください(図13)。 Font Awesomeは、アイコンを一種 のフォントとして、ベクトル形式のス ケーラブルなデータから作成できるよ うにするツールキット(http://fortaw e s o m e . g i t h u b . i o / F o n t -Awesome/)。 図12:「Android-Bootstrap」のコンポーネントたちライブラリープロジェクトを導入してみよう
17 -2 -4
外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章
ライブラリープロジェクトをインポートする
「ライブラリープロジェクト」は通常のAndroidプロジェクトと同じ構造を持つの で、そのままEclipseにインポートできます。zipファイルを解凍し、ライブラリープロジェ クトをインポートしましょう(図14)。 図13:「Android-Bootstrap」 のzipファイルをダウンロード する解凍したディレクトリをインポート対象に選択すると、「AndroidBootstrap」と 「AndroidBootstrapTest」の2つのプロジェクトが表示されます(図15)。両方 インポートしても問題ありませんが、「AndroidBootstrapTest」は今回利用しない のでチェックを外しておきましょう。 インポートが成功すれば「Package Exprolrer」に「AndroidBootstrap」が 追加されます(図16)。
ライブラリープロジェクトを参照する
次に、新しいAndroidプロジェクトを作成してください。ここでは「UseAndroid Bootstrap」という名前のプロジェクトを作成したものとして話を進めます。新しく作 成したAndroidプロジェクトのディレクトリの上で右クリックし、「Properties」を選 択してください(図17)。 図15:「AndroidBootstrap」を選択してインポートする 図16:「Package Exprolrer」にプロジェクトとして「AndroidBootstrap」が追加された外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章 「Android」の項目を開き、「Library」セクションの「Add...」ボタンを押してくだ さい(図18)。 図17:Androidプロジェクトの「Prop erties」を開く
すると参照できるライブラリープロジェクトの一覧が表示されるので、「AndroidB ootstrap」を選択し、「OK」ボタンを押します(図19)。 元のダイアログの「Library」セクションに「AndroidBootstrap」が追加されて いれば成功です(図20)。 図 1 9:参 照 できる ライブ ラ リープロジェクトの一覧から 「AndroidBootstrap」を選ぶ 図20:選択した「AndroidBootstrap」が、「Library」セクションに参照しているライブラリーとして追加された
外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章
動作確認
正しく準備ができたか確認してみましょう。新しく作ったプロジェクトの「MainAct ivity.java」の冒頭に、リスト13のような「import」文を記述し、エラーが発生し なければ準備完了です。 もしエラーになる場合はプロジェクトを一度「clean」したり、再ビルドするなどして みてください。 「Android-Bootstrap」はいくつかのカスタムViewを提供しています。そのうち の一つである「BootstrapButton」を使ってみましょう。リスト14のようにレイアウト ファイルに「BootstrapButton」を定義してください。 アプリケーションを起動すると図21のような表示になるはずです。 リスト13:MainActivity.java(導入したライブラリーのクラスをインポートする) import com.beardedhen.androidbootstrap.BootstrapButton; リスト14:activity_main.xml(BootstrapButtonの定義) <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:library="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <com.beardedhen.androidbootstrap.BootstrapButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:text="Hello Bootstrap!" library:bb_type="success" /> </LinearLayout> 図21:アプリ画面に 「BootstrapButton」 が表示されたAndroid-Bootstrap の BootstrapButton を使う
17 -2 -5
「BootstrapButton」のレイアウトの定義に見慣れない記述がありました。レイア ウトの要素には通常「android:」をプレフィクスとした属性値を定義しますが、「Boo tstrapButton」ではリスト15のように異なるプレフィクスを持った属性を定義して います。 これは「カスタム属性」というAndroidの機能です。Androidではレイアウトファイ ルで利用する属性値を自分で定義できます。「Android-Bootstrap」は「カスタム 属性」を各種コンポーネントに定義し、レイアウトファイル上で様々な設定ができるよう になっています。 次に「BootstrapButton」の「bb_type」属性の値を変更してみましょう(リス ト16)。 アプリケーションを実 行すると図 2 2のような表 示になります。このように 「Android-Bootstrap」はカスタム属性によって様々な表示を簡単に設定できる 仕組みを提供しています。 リスト15:activity_main.xml(BootstrapButtonに指定したプレフィクスが異なる属性) library:bb_type="success" プレフィクスは「library:」 この例では「library:」というプレフィクスを使っていますが、特に決まりはありませ ん。このプレフィクスは「名前空間」と呼び、属性の名前が衝突しないために用いられま す。カスタム属性のための名前空間は、レイアウトファイルの冒頭の「xmlns」属性定義 で自由に決められます。ここでは「xmlns:library="http://schemas.android.com/ apk/res-auto"」のように定義し、「library:」というプレフィクスを用いることを宣言し ています。
check!
リスト16:activity_main.xml(bb_typeを変更する) library:bb_type="danger"カスタム属性
17 -2 -6
外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章
ライブラリーが定義しているカスタム属性を知るには
UIコンポーネントを提供するライブラリーでは、カスタム属性を定義している場合 が多いです。ライブラリーが定義しているカスタム属性を知る方法として以下が挙げ られます。 ・ ドキュメントを読む ・ ソースを読む 基本的にまずはドキュメントを探して読むことになるでしょう。例えば「Android-Bootstrap」の「BootstrapButton」の使い方は以下のページに解説がありま す。 ・ Bootstrap Button:https://github.com/Bearded-Hen/Android-Bootstrap/wiki/Bootstrap-Button 「Android-Bootstrap」には比較的ていねいなドキュメントが揃っていますが、 中にはドキュメントがなかったり、カスタム属性についての記述が不足しているライブ ラリーもあります。参考になるドキュメントがない場合は、ライブラリーのソースを読んで 調べることになります。ソースを読んでカスタム属性を理解する
Eclipseにインポートした「Android-Bootstrap」の中を覗いて、「Bootstrap Button」クラスのカスタム属性について調べてみましょう。「Android-Bootstrap」 の「res/values/attrs.xml」を開いてください(図23)。 図22:カスタム属性 「bb_type」を「dang er」に変更した結果リスト17に「attrs.xml」ファイルの冒頭部分を抜粋します。 「declare-styleable」要素の「name」属性に「BootstrapButton」という記述があります。 これは「BootstrapButton」のカスタム属性の宣言を表します。 「declare-styleable」要素の中に複数の「attr」要素を持っています。「attr」要素には属 性名と、それに対して指定できる値の種類を定義しています。 図23: 「Android-Bootstrap」の「att rs.xml」を開く リスト17:AndroidBootstrap-attr.xml(冒頭部分) <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="BootstrapButton"> <attr name="bb_type" format="string"/> <attr name="bb_icon_left" format="string"/> <attr name="bb_icon_right" format="string"/> <attr name="bb_roundedCorners" format="boolean"/> <attr name="bb_text_alignment" format="string"/> <attr name="bb_size" format="string"/>
<attr name="bb_text_gravity" format="string"/> <attr name="android:textSize"/> <attr name="android:text"/> <attr name="android:enabled"/> <attr name="android:layout_width"/> </declare-styleable> <!-- 省略 -->
外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章 これで「BootstrapButton」の持つカスタム属性はわかりました。次はこれらの 属性がどのように使われているかを調べます。すべて調べるのは大変なので、代表と して「bb_type」属性がどのように使われているかを「BootstrapButton」クラスの ソースコードを読んで確認してみましょう。「BootstrapButton」クラスは「src/ com/beardedhen/androidbootstrap/BootstrapButton.java」で定義され ています(図24)。 「BootstrapButton.java」を開き、「bb_type」をキーにしてソースコード内を検 索をすると、140行目に「bb_type」属性を扱う処理が見つかります(リスト18)。 将来変更される可能性があるので、ソースコードのハッシュ値を記載しておきま す。「9067416920a2a9a000a77280010fdc580aaf06b1」 カスタム属性を定義すると、Rクラスの「styleable」にIDが追加されます。ID名 は「declare-styleable」要素で定義した「name」属性と「attr」要素の 「name」属性を「_」(アンダースコア)でつないだものになります。このIDを使って 「TypedArray」クラスから指定された値を取り出すことができます。「Bootstrap Button」の「bb_type」属性の場合は、「BootstrapButton_bb_type」という 名前になります。 図24:「BootstrapB utton.java」を開い て調べる リスト18:BootstrapButton.java(140行目前後)
113:private void initialise( AttributeSet attrs ) {
-省略-121: TypedArray a = getContext().obtainStyledAttributes(attrs, 122: R.styleable.BootstrapButton);
-省略-126: String bootstrapType = "default";
-省略-140: if (a.getString(R.styleable.BootstrapButton_bb_type) != null) { 141: bootstrapType = a.getString(R.styleable.BootstrapButton_bb_type); 142: }
「TypedArray」クラスは「Context」クラスの「obtainStyledAttributes」メ ソッドで取り出します。この時引数に「AttributeSet」クラスのオブジェクトと「R.sty leable.BootstrapButton」を渡します。「AttributeSet」オブジェクトは、View のコンストラクタで受け取ったものを使います。 Viewのコンストラクタが3種類あったことを覚えているでしょうか。11章の第1節で カスタムViewを作成する際に、「XMLより呼び出す際のコンストラクタ」として解説 したコンストラクタの引数に「AttributeSet」オブジェクトが渡ってきます。この「Att ributeSet」オブジェクトには、レイアウトファイルで定義した属性値が入っています。 「bb_type」の属性値は「String」なので、「TypedArray」クラスの「getStri ng」メソッドで取り出します。取り出した値は「bootstrapType」にセットしています。 次は「bootstrapType」がどこで使われているかを探します。「bootstrapTy pe」をキーにしてソースコード内を検索すると、240行目にリスト19のような実装が 見つかります。 241行目の「if」文は「roundedCorners」という変数名から「ボタンを角丸にす るかどうか」を判定していることがわかります。今回は特に角丸の指定はしていなかっ たので245行目の処理に進みましょう。245行目では「bbuttonTypeMap」という 変数の「get」メソッドに「bootstrapType」を渡しています。
「bbuttonTypeMap」は「Map<String, BootstrapTypes>」クラスです。 「get」メソッドで「BootstrapTypes」クラスのインスタンスを取り出せます。そのイン
リスト19:BootstrapButton.java(240行目前後)
26: private static Map<String, BootstrapTypes> bbuttonTypeMap;
-省略-36: private boolean roundedCorners = false;
-省略-125: BootstrapTypes type = null;
-省略-240: //get the correct background type 241: if(roundedCorners == true) 242: { 243: type = bbuttonTypeMapRounded.get(bootstrapType); 244: } else { 245: type = bbuttonTypeMap.get(bootstrapType); 246: } 247: 248: //set up as default 249: if (type == null) 250: { 251: type = BootstrapTypes.DEFAULT; 252: } 253:
254: //apply the background type
255: layout.setBackgroundResource(type.backgroundDrawable);
256: lblLeft.setTextColor(getResources().getColor(type.textColour)); 257: lblMiddle.setTextColor(getResources().getColor(type.textColour)); 258: lblRight.setTextColor(getResources().getColor(type.textColour));
外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章 スタンスを「type」という変数にセットし、その後255行目で利用しています。 次は「bbuttonTypeMap」をどのように初期化しているか、「BootstrapTyp es」クラスがどのようなクラスなのかを見ていきます。まずは「BootstrapTypes」クラ スです。「BootstrapTypes」クラスは84行目に定義されています(リスト20)。 「BootstrapTypes」クラスは「class」ではなく「enum」と宣言されています。 「enum」は列挙型を表します。 列挙型は通常のクラスと同じようにコンストラクタやフィールドやメソッドを持ちます。 ただしインスタンスは「enum」内に宣言した列挙子のみに限られるという特徴があり ます。あらかじめ宣言したもの、数しかインスタンスが存在しないことが保証されている ため、「switch」文で比較したり定数として扱うことができます。 「BootstrapTypes」クラスは、フィールドとして「backgroundDrawable」(背 景のdrawable)と「textColour」(文字色)を持った単純なクラスです。列挙子と して「DEFAULT」や「PRIMARY」などが宣言されています。列挙子を宣言す る際に、背景のdrawableと文字色のIDを渡しています。これによりボタンの色のバ リエーションを定義しています。 次は「bbuttonTypeMap」の初期化です。41行目のstaticイニシャライザー で、キーに対応する「BootstrapTypes」クラスをセットしていることがわかります(リ スト21)。 staticイニシャライザーは、クラスが初めてクラスローダーに読み込まれる時に一 度だけ実行されるブロックのことです。クラスがインスタンス化される時ではない点に 注意してください。 リスト20:BootstrapButton.java(84行目以降)
84: private enum BootstrapTypes 85: { 86: DEFAULT(R.drawable.bbuton_default, R.color.black), 87: PRIMARY(R.drawable.bbuton_primary, R.color.white), 88: SUCCESS(R.drawable.bbuton_success, R.color.white), 89: INFO(R.drawable.bbuton_info, R.color.white), 90: WARNING(R.drawable.bbuton_warning, R.color.white), 91: DANGER(R.drawable.bbuton_danger, R.color.white), 92: INVERSE(R.drawable.bbuton_inverse, R.color.white),
-省略-102: private int backgroundDrawable; 103: private int textColour;
104:
105: BootstrapTypes(int backgroundDrawable, int textColour) 106: {
107: this.backgroundDrawable = backgroundDrawable; 108: this.textColour = textColour;
109: } 110: }
これですべての情報がそろいました。「bb_type」属性で指定した値は「bbutto nTypeMap」に登録された「BootstrapTypes」クラスを取り出すためのキーとし て利用されていました。「BootstrapTypes」は背景のdrawableと文字色を持つ クラスで、このクラスが持つ値を使ってViewの表示色などを変更していることがわか りました。 少し大変だったかと思います。しかしソースを読むことによって「bb_type」属性 の役割がわかっただけでなく、「表示を属性値によって簡単に切り替える仕組み」 がどのように実現されているかもわかりました。また「bb_type属性の値の種類が7 つあること」や「角丸表示の設定があること」や「enumクラスの使い方の参考」など も得られました。ソースコードを読むことで非常に多くの学びが得られます。 Androidアプリケーションで利用するライブラリーのほとんどはオープンソースで す。前項で「Android-Bootstrap」のカスタム属性を調べることができたのも 「Android-Bootstrap」がオープンソースだからです。オープンソースのソフトウェ アには「オープンソースライセンス」が定義されています。オープンソースのソフトウェア を利用する場合、「オープンソースライセンス」に記載されている条件に従う必要が あります。 オープンソースライセンスには沢山の種類があります。本項では近年のオープン ソースのライブラリーでよく利用されている「Apache License 2.0」、「MIT Lice nse」に加え、コピーレフトという思想に則った「GPLライセンス」について簡単に解 説します。
リスト21:BootstrapButton.java(41行目以降)
41: static{ 42:
43: bbuttonTypeMap = new HashMap<String, BootstrapTypes>(); 44: 45: bbuttonTypeMap.put("default", BootstrapTypes.DEFAULT); 46: bbuttonTypeMap.put("primary", BootstrapTypes.PRIMARY); 47: bbuttonTypeMap.put("success", BootstrapTypes.SUCCESS); 48: bbuttonTypeMap.put("info", BootstrapTypes.INFO); 49: bbuttonTypeMap.put("warning", BootstrapTypes.WARNING); 50: bbuttonTypeMap.put("danger", BootstrapTypes.DANGER); 51: bbuttonTypeMap.put("inverse", BootstrapTypes.INVERSE);
-省略-ライブラリーとライセンス
17 -2 -7
外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章
GNU General Public License(GPLライセンス)
「GPLライセンス」は「オープンソース」という概念が提唱される時代より前に作ら れたライセンスのひとつです。ライセンス条項はコピーレフトの思想に則っています。コ ピーレフトは著作権(コピーライト)を保持したまま、すべての者がその著作物の利 用、再頒布、改変ができなければならないという考え方です。 このため、「GPLライセンス」を持ったオープンソースのライブラリーを利用する場 合、ライブラリーを利用したアプリケーションのソースコードにも「GPLライセンス」が適 用されます。つまりそのアプリケーションのソースコードも公開しなければならないという ことになります。Apache license 2.0
「Apache license 2.0」は、「Apacheソフトウェア財団(ASF)」が策定した オープンソースライセンスです。「Apache license 2.0」ではソースコードの開示義
務はありません。
「Apache license 2.0」ライセンスのライブラリーに「NOTICE」ファイルが含ま れている場合、その内容についてアプリケーション上で表示する必要があります。多 くのアプリケーションでは「NOTICE」ファイルの有無に関係なくライブラリー名、著 作権者、ライセンス条項を表示する場合が多いです。
MITライセンス
「MITライセンス」は、「マサチューセッツ工科大学」が公開したオープンソースラ イセンスです。非常にシンプルなライセンスで原文も20行程度しかありません。 利用にあたっては、著作権表示と許諾表示を行う必要があります。「MITライセ ンス」もソースコードの開示義務はありません。ライセンスを確認しよう
以上、代表的なオープンソースライセンスについてざっくり説明をしました。オープ ンソースライセンスには様々な種類があり、それぞれで条件が異なります。オープン ソースのライブラリーを利用する時は、必ずライセンスの確認をし、守るべき条件を確 認しましょう。図25は、「Apache license 2.0」や「MITライセンス」の著作権表 示や許諾表示の例です。既存のアプリケーションがどのようにオープンソースライセ ンスを取り扱っているか参考にするとよいでしょう。外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章 1.Android-Bootstrapを使ってプロフィール画面を作ってみましょう。 Android-Bootstrapのコンポーネントを使ってプロフィール画面を作ってみましょ う。以下の図26の例は「BootstrapButton」「FontAwesomeText」「Boots
trapCircleThumbnail」を使っています。この例を再現してもよいですし、独自に デザインしても構いません。 2.Android-Bootstrapのライセンスを調べてみましょう。 「Android-Bootstrap」のライセンスの種類は何か、利用にあたって何をしなけ ればならないか調べてみましょう。
演習問題
本節では「ライブラリープロジェクト」の生い立ち、その使い方、オープンソースライ センスについて学びました。「ライブラリープロジェクト」はソースコードをインポートして 利用する形式なので、ライブラリー自身のソースコードを参照しやすいです。Andr oidアプリケーションを作る時、Android自身のソースコードを参照することがよくあり ます。ソースコードを読めば、ドキュメントに書かれていない詳細な処理や、Andro idバージョン毎の違いを知ることができます。普段からソースコードを読む習慣を身 につけておきましょう。 Androidはオープンソース Androidのソースコードのダウンロード方法は以下のページで確認できます。 Downloading the Source:https://source.android.com/source/downloading. html
Androidのソースコードは巨大で、すべてのソースコードをダウンロードすると、数十 GBの容量になります。気軽にダウンロードできるサイズではありません。Androidの ソースコードを簡単に参照できるサービスがいくつかあります。まずはこれらのサービ スを利用してソースコードを読むとよいでしょう。
Developer Collaboration Project:https://sites.google.com/site/devcollabora tion/codesearch
GrepCode:http://grepcode.com/project/repository.grepcode.com/java/ext/ com.google.android/android/
check!
まとめ
外 部 ラ イ ブ ラ リ ー の 利 用 と 作 成 第 17 章 ・ ライブラリープロジェクトの作り方 ・ 作成したライブラリープロジェクトの使う ・ ライブラリープロジェクトとminSdkVersionの注意点 ・ Activityをライブラリープロジェクトに含める場合の注意点