2011/08/11

Android Project で Is Library を使う場合、res の管理に注意

以前、Android プロジェクトを jarライブラリ化する というエントリで
res以下を使用したい場合は、上記の Is Library を使用することでライブラリ化することが可能です。
と書いたのですが、最近、Is Library を使っていても res 以下の扱いは注意しなければいけないことに気づきました。
具体的には、Library と Application(使用する側)に同じ名前のリソースがあると、コンパイルエラーにはならないが、実行時におかしなことが起こるのです。

この辺の事情は、以下のサイトに詳しく書いてあります。

このページを見ると、
You cannot export a library project to a JAR file
A library cannot be distributed as a binary file (such as a jar file). This is because the library project is compiled by the main project to use the correct resource IDs.
と書いてありますね。
Google は公式にJARファイルによるライブラリ化を否定しているわけです。残念なことです。

JARファイルを使用できないとなれば、Is Library でライブラリ化したいわけです。
しかし、その際も注意が必要です。
Resource conflicts
Since the tools merge the resources of a library project with those of a dependent application project, a given resource ID might be defined in both projects. In this case, the tools select the resource from the application, or the library with highest priority, and discard the other resource. As you develop your applications, be aware that common resource IDs are likely to be defined in more than one project and will be merged, with the resource from the application or highest-priority library taking precedence.
と書いてあるのです。
(Is Library を使っても)ライブラリとアプリケーションで resource ID を共有するから、リソースが重複するとどちらかが破棄されるよってことです。

少し実験してみました。
Application というプロジェクトと Library というプロジェクトを作成し、Application が Library を使用している状態にします。
Library は「Hello Library!」と表示するだけのダイアログを提供しています。(「Hello Library!」は string.xml の中でhelloというnameで定義)

この時、Library の中にあるリソースが以下のように同じ名前だと問題なのです。

Application プロジェクトを実行してみると、コンパイルエラーもなく、実行することが出来ました。
しかし、実行結果は以下のようになってしまいます。

本来、「Hello Library!」と表示されてほしいところに、「Hello World, ApplicationActivity!」と表示されてしまいました。

この現象、Applicationプロジェクトの中に生成されている R.java を見てみると納得がいきます。


ちゃんとネームスペース毎に R.java は生成されているのですが、DiffをとってみるとIDが同じです。
今回、Library の layout/main が Application の layout/main に上書きされてしまったので、ダイアログの中身が想定と違うものになってしまったというわけです。

2011/9/30 追記
ダメですよ、ってことだけ書いて放置してしまっていたので、どうすれば良いのかを以下に追記しました
Android Project で res を使う Library を作る



0 件のコメント: