Rの二乗
先日のエントリでは外部のライブラリィプロジェクトをアプリケーションプロジェクトに取り込む際の解決策を書いた。
Androidの場合は、ライブラリィをAndroidプロジェクトとして作成したならば、プロジェクトではなく、ソースコードとして参照する必要がある。
しかし、この方法でも上手くいかないことが判った。それはライブラリィ・プロジェクト側でもAndroid リソースクラス(Rクラス)を使用している場合である。
以前のエントリで紹介した方法の場合、ライブラリィをソースコードとして取り込む場合、以下のようなディレクトリ構成になると思う。(順不同)
$PROJECT_ROOT | +--- gen (自動生成されたアプリケーションソース) | | | +-- R.java × | +--- src (アプリケーション・ソース) | +--- lib_src (ライブラリィ・ソース) ※LIB_PROJECT_ROOT\srcへのリンク | +--- lib_gen (自動作成されたライブラリィ・ソース) ※LIB_PROJECT_ROOT\genへのリンク | | | +-- R.java × | +--- res (リソース) | | | +-- layout | | | +-- main_layout.xml
同一プロジェクト中に自動作成されたR.javaが二つ存在しているが、パッケージが違うため、存在自体に問題は無い。問題なのは、リソース(Rクラス)への参照がプロジェクト外に及ぶ場合だ。
例えば、ライブラリィ側では共通で使用する独自のコンポーネントを提供していたとしよう。
独自のコンポーネントは、標準のビューを拡張しており、属性 "guidance" が追加されている。
$LIB_PROJECT_ROOT | +--- gen (自動生成されたソース) | | | +-- R.java | +--- src (ライブラリィ・ソース) | | | +-- jp.hoge | | | +-- GuidanceView.java | +--- res (リソース) | | | +-- values | | | +-- attr.xml
拡張されたコンポーネントのための属性は attr.xmlに
-
- attr.xml
-
- R.java (attr.xmlにより追記された分)
public final class R { public static final class attr { public static final int guidance=0x7f010001; } : : public static final class styleable { public static final int[] GuidanceView = { 0x7f010001 }; public static final int GuidanceView_guidance = 0; }; }
拡張されたコンポーネントはレイアウトにクラス名を明示することで、内部インフレータ(Inflator)により実体化される
-
- main_layout.xml (拡張されたビューを抜粋)
hoge:guidance="URLを入力してください">
ネームスペースhogeの指定は重要だ。この属性で指定されているURIの末尾が参照されるパッケージとなるからだ(これもわかりにくかった)。
この例の場合、xmlns:hoge="http://schemas.android.com/apk/res/jp.hoge" の末尾にあたる jp.hoge.R クラスがリソースとして参照されることになる。
インフレートされたコンポーネントは、コンストラクタ内で上記リソースを使って、レイアウトに指定された新たな属性を読み込むのである。(ここもわかりにくかった..)
-
- jp.hoge.view.GuidanceView#GuidanceView
public GuidanceView(Context context, AttributeSet attrs) { super(context, attrs); //attr.xml経由で拡張されたプロパティを取得 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GuidanceView); this.guidance = a.getString(R.styleable.GuidanceView_guidance); }
これで完璧なはずだったのだが、実際に上記のレイアウトを記述するとエラーになる。
ERROR No resource identifier found for attribute 'guidance' in package 'jp.hoge'
ならばとビルドし直すと、プロジェクト下のR.javaが消えてしまい、全ての参照がエラーとなってしまう。
R を解決できません
ということで、ADT Plugingで作成したプロジェクト、レイアウトからは外部プロジェクトのリソース(Rクラス)を参照できないのか、又は、プロジェクト中で管理できるリソース(R.java)は一つだけようである。
このままではやはり、共通ライブラリィを皆で共有して使う、という方法は採れないことになる。
一定の条件を満たしたアセンブリ同士ならば共有可能な、.NETのような仕様だと楽ちんなんだがなぁ。 今後に期待か。
解決(妥協する)方法はありそうなのだが、それは次回に。