techium

このブログは何かに追われないと頑張れない人たちが週一更新をノルマに技術情報を発信するブログです。もし何か調査して欲しい内容がありましたら、@kobashinG or @muchiki0226 までいただけますと気が向いたら調査するかもしれません。

AndroidライブラリからアプリケーションプロジェクトのBuildConfigの値を参照する

Androidアプリ開発の際にオープンソースのライブラリを組み込むことが多いと思います。
そういった中でアプリのデバッグの時にはライブラリのログを出したいとかデバッグの時だけこういった挙動をしたライブラリがほしいことかがあります。

そこで今回はaarからアプリのBuildConfigのDEBUGを読み取りその情報から挙動を変える方法をご紹介します。

BuildConfigの参照先

Androidのアプリ開発およびライブラリ開発を行うと自動生成されるBuildConfigファイルがあります。
これは現在のビルド設定はどのようなっているかを定数で保有しているファイルで次のような内容が生成されます。

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "パッケージ名";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0";
}

これはデバッグビルドでかつFLAVORの定義はなしの時の自動生成ファイルになります。
これが各モジュールごとに自動生成され、ビルド時にAPKまたAARに内包されます。
BuildConfigファイルはアプリ用のモジュールを抱えたプロジェクト内にライブラリのモジュールも用意している場合は次のような構成になります。

.
├── <アプリモジュール>
│   ├── build
│   │   └── generated
│   │       └── source
│   │           └── buildConfig
│   │               ├── debug
│   │               │   └── <パッケージ>
│   │               │       └── BuildConfig.java         <——(1)
│   │               └── release
│   │                   └── <パッケージ>
│   │                       └── BuildConfig.java         <——(1)
│   └── src
└── <ライブラリモジュール>
    ├── build
    │   └── source
    │       ├── debug
    │       │   └── <パッケージ>
    │       │       └── BuildConfig.java         <——(2)
    │       └── release
    │           └── <パッケージ>
    │               └── BuildConfig.java         <——(2)
    └── src

アプリモジュールは(1)のBuildConfigを読みます。
ライブラリモジュールのBuildConfigは(2)のものが読み込まれます。
そのためライブラリモジュール側でBuildConfig.DEBUGを使おうとすると(2)を読み込んでしまうためアプリモジュールの内容にしたがって制御することができません。
またライブラリを公開する場合は基本的にリリースビルドで公開しますので多くの場合は公開した時点でBuildConfigのDEBUGはfalseになります。 そのためライブラリをアプリに組み込んだ時にライブラリをデバッグモードとして動かうことが無理になります。

Gradleの設定でBuildConfig

ライブラリモジュールを抱えたアプリの場合は次の方法が可能です。 ライブラリの側のbuild.gradleを次のようにします。

android {
    publishNonDefault true
}

これでアプリ側からライブラリビルドをするときの指定が可能になります。 次にアプリ側のbuild.gradleは次のようにします。

dependencies {
    releaseCompile project(path: ':library', configuration: 'release')
    debugCompile project(path: ':library', configuration: 'debug')
}

これでデバッグビルドかリリースビルドかによってビルド指定ができるようになり、その内容に合わせたBuildConfigがaarに自動生成され利用されるようになります。
この方法には欠点がありaarファイルを配布しているものに関しては利用できません。
理由としてはすでにビルド済みのaarファイルを配布しているためBuildConfigを変更させることなどできないからです。
また、アプリ側にライブラリモジュールの設定を意識した記述をbuild.gradleを書かせるのはおかしいように思います。

アプリ側のBuildConfigを参照する

リリースビルドしたaarファイルからアプリ側のBuildConfigを参照するにはライブラリのソースコード上で次のような実装を行います。

AARファイルからアプリのBuildConfigのDEBUGを読み込む

ここではライブラリにContextを渡し、そのContextからアプリのパッケージ名をgetPackageName()で取得して、自動生成されるBuildConfigのクラスを直接参照するやり方をとっています。
BuildConfigがアプリモジュールがパッケージ名から自動生成されることを逆手に取った方法で参照することでaarでリリースされているものでも参照できるようになります。

この方法を使ってBuildConfigの内容が取得できましたのでDEBUGがtrueかfalseかによって処理を分けることができるようになります。