2016年04月19日

Android Studio でライブラリ化まとめ

 Android Studio で再利用できるコードをライブラリ化したり、別のプロジェクトから参照する方法や、その際の罠の覚え書きです。
 「Android Studio ノウハウまとめ」に属する内容だけど、そこそこ長くなりそうなので独立記事にした。

ライブラリプロジェクトの作り方
 ざっと調べた限りでは、Android Studio ではライブラリだけのプロジェクトというのは作れないみたい。普通にアプリとしてプロジェクトを作って、モジュールを分けます。
  1. まず普通に、空の Android アプリのプロジェクトを作成する。プロジェクトには、デフォルトのモジュールとして app モジュールが作られます。
  2. [File] > [New] > [New Module] で 「Android Library」 を作成すると、ライブラリモジュールの雛形が作られる。
  3. app モジュールからライブラリモジュール内のクラスなどを使用するには、app モジュールの build.gradle を編集し、dependencies に以下の一行を追加。
    compile project(':ライブラリモジュール名')
    
 これで、アプリとライブラリを分割できたので、再利用したいコードやリソースは、ライブラリモジュール内に書いていけばOK。最初にできた app モジュールは、ライブラリの動作テスト用アプリにしましょう。
別のプロジェクトからライブラリモジュールを利用
 上の手順で、再利用したいコードの分離はできましたが、このままでは結局このプロジェクトでしかライブラリモジュールを使えませんね。他のプロジェクトからこのライブラリモジュールを参照したい場合は以下のようにすればいいようです。

 ここでは例として、以下のようなフォルダ構成で、NewApplication プロジェクトから、MyLib プロジェクトの testlib モジュールを利用したいとします。
+-[MyLib]            ←ライブラリプロジェクト
|   +-[app]
|   +-[testlib]      ←ライブラリモジュール
|
+-[NewApplication]   ←別のアプリのプロジェクト
    +-[app]          ←ここから testlib を利用したい
  1. NewApplication 側の setting.gradle を編集。
    incluede に testlib を追加して、testlib の参照先フォルダを指示する。
    include ':app', ':testlib'
    project(':testlib').projectDir = new File(settingsDir, '../MyLib/testlib')
    
    上記の場合、settingsDir (= setting.gradle のフォルダ) からの相対パスでの指定。下記のように絶対パス指定もできるけど、共同作業で困るので普通はしませんね。
    project(':testlib').projectDir = new File('D:/project/MyLib/testlib')
    
  2. あとは、NewApplication 側の app の build.gradle も編集して、dependencies にライブラリモジュールを追加するだけ。
    compile project(':testlib')
    
 これで、NewApplication から testlib のクラスやリソースの利用はもちろん、まるで同じプロジェクトかのように testlib 側のソースも修正できるし、連動してビルドされるようになる。
ライブラリモジュールのビルド設定
 Build Variant で debug や release などのビルド設定を変えた場合、ライブラリモジュールも当然連動してその設定でビルドされると思うのですが、連動してませんので注意。ライブラリモジュールはデフォルトだと常に release ビルドになる らしい。連動させたければ以下のように。
  1. ライブラリモジュールの build.gradle を編集。publishNonDefault を true に設定する1行を追加。これで、app 側から、ライブラリのビルド設定を指示できるようになる。
    android {
        ...
        publishNonDefault true
        ...
    }
    
  2. app 側の build.gradle を編集。今まで dependencies 内で
    compile project(':testlib')
    
    などと書いていた場所を、Build Variant ごとに別処理をするように書き換える。
    debugCompile project(path: ':testlib', configuration: 'debug')
    releaseCompile project(path: ':testlib', configuration: 'release')
    
 これで、Build Variant が debug の時はライブラリも debug、release の時は release でビルドされるようになる。もし Build Variant を増やした場合も、その時はどっちでビルドすべきか個別で指示できる。
BuildConfig はアプリとライブラリで別
debug ビルドと release ビルドで処理を変えたい場合、
if ( BuildConfig.DEBUG )
{
    // debug 時の処理
}
などと書きますが、この BuildConfig はモジュールごとに別に作られてるので注意。
20160420a.png
 ソース内で BuildConfig を初めて使う場合、エディタが気をつかって自動で import を書いてくれますが、よく見ずにうっかりライブラリ側の BuildConfig をインポートしてしまうと、以後 debug ビルドなら動くはずのコードが動かなかったり、謎の現象に悩まされます。
アプリモジュールとライブラリモジュールのリソースの関係
 ライブラリモジュールを作成すると、ライブラリ側にも AndroidManifest.xml やリソース用のフォルダが自動的に作られますが、AndroidManifest.xml の各種設定やリソースのIDは、アプリとライブラリで独立してる訳じゃなくて、ビルド時に無理矢理マージしてるだけ なので、それを意識して使わないと意図せぬ事態が起きます。以下は特に注意。
  • もし ライブラリとアプリで同じIDのリソースがあると、アプリ側の値で上書きされてしまう ので、上書きされたくなければ、ライブラリ側のIDには全てライブラリ名のプレフィックスをつけるなどして、かぶらないように工夫する。
    逆に、意図的にアプリ側から上書きさせる事で、レイアウトのマージンなどをアプリごとに微調整したりもできるので、何事も使いよう。
  • ライブラリモジュール側の AndroidManifest.xml に、uses-permission とか、あまり余計な事を書かない
    例えばライブラリ内に、ネットとか録音とか、いろんなヘルパークラスを詰め込んだとして、ライブラリ側の AndroidManifest.xml にそれらの機能のための uses-permission を書いてしまうと、たとえその機能をアプリ側で使ってなくても問答無用でパーミッションが付いてしまいます。
    パーミッション指定などは、アプリ側の AndroidManifest.xml に個別に書きましょう。

posted by ひこざ at 23:36| Comment(0) | 開発 - Android
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。