私はいくつかの再利用可能なAndroidコードを自分のアプリケーション内で使用するために他の開発者に配布したいと考えています。コードにはいくつかのリソース依存関係(レイアウト、xmlおよびpngドローアブル))があります。単一のパッケージ(Jarファイル)内に含めて参照できるようにする。
これは可能ですか?可能であれば、これを行うための最良の方法は何ですか?
楽天的なニュースはありません。一般に、あなたが期待するほど簡単にあなた自身のパッケージを配布することはできません。主な問題は自動生成されたRファイルです。あなたはおそらくそれをいくつか参照しています-あなたはあなたのレイアウトとドローアブルを持っています。ライブラリのユーザーは自分のRファイルを持ちます-ライブラリが提供するものではなく、自分のリソースのIDを含みます。
ドローアブルリソースの場合、Rファイルなしで従来の方法で読み取ることができます。しかし、私が知る限り、外部のxmlファイルからレイアウトを拡張することはできません。
したがって、ここでの醜いハックは、ライブラリをすべてのリソースと一緒に配布することです。そのユーザーは、自分の "res"フォルダにコピーする必要があります。正直なところ、問題に対する適切な解決策はありません...すみません。よろしく!
Androidは/res
フォルダの下のリソースファイルを使用してR
クラスを自動的に作成するため、R
クラスをfinal static
として使用することは不可能です。
jar
ファイルでres
ファイルを使用するための素晴らしい解決策を見つけました。ここに私がそれをした方法があります:
jar
ファイルにエクスポートされるソースコードでは、コンパイル時に最終的な静的メモリアドレスに置き換えられるため、使用しないでくださいR
変数。 R
を使用する代わりに、以下の独自のメソッドを作成しました。
public static int getResourceIdByName(String packageName, String className, String name) {
Class r = null;
int id = 0;
try {
r = Class.forName(packageName + ".R");
Class[] classes = r.getClasses();
Class desireClass = null;
for (int i = 0; i < classes.length; i++) {
if (classes[i].getName().split("\\$")[1].equals(className)) {
desireClass = classes[i];
break;
}
}
if (desireClass != null) {
id = desireClass.getField(name).getInt(desireClass);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return id;
}
たとえば、main.xml
という名前のレイアウトがある場合、次のメソッドを呼び出すことで取得できます。
int id = getResourceIdByName(context.getPackageName(), "layout", "main");
id
が「text1」である文字列がある場合、メソッドを呼び出すことで取得できます
int id = getResourceIdByName(context.getPackageName(), "string", "text1");
このメソッドは、実行時にリソースIDを提供します。リフレクションAPIを使用して、実行時にR
のステータスを取得します。
この方法を使用すると、R
変数の使用を回避できます。
res
ファイルをターゲットプロジェクトにコピーします。
ビルド。
レイアウト:
Javaソースのハードコード
xml&png:
xml&pngをプロジェクトのsrcフォルダーにコピーし、パッケージをjarにコピーします。
a.pngをsrc/com/example/testにコピーします
次のようにロードしますJavaコード:
InputStream is = YourClassName.class.getClassLoader().getResourceAsStream("com/example/test/a.png");
if ( null != is )
{
Bitmap bmp = BitmapFactory.decodeStream(is);
Android SDKのaapt
ツールで次のオプションが許可されていることがわかりました。
--non-constant-id Make the resources ID non constant. This is required to make an R Java class that does not contain the final value but is used to make reusable compiled libraries that need to access resources.
これは有望に聞こえますが、私はこれを試したことがないので、うまくいくかどうかはわかりません。これは、上記の@ J.J.Kimの投稿で取り上げられている問題を回避するためだと思います。
Androidメソッドを使用して、リソースIDを動的に取得できます。
int preferences = context.getResources().getIdentifier("preferences", "xml", context.getPackageName());
後でリソースを新しいプロジェクトに含める(コピーする)必要があります。
こんにちはこれは遅い応答だと思いますが、それでも私はAARについて何を通知するべきかだけです
Android ARchive-このファイルにはresファイルとマニフェストファイルを保持できるため、他の開発者はaarをプロジェクトにインポートしてコードをコンパイルするだけです。
これにより、マニフェストマージエラーが発生する可能性があります。マニフェストでreplaceプロパティを使用するための修正であり、配布前に確認する必要があります。
私は ser558185 ソリューションを使用していましたが、これはより簡単な方法です。リソースが(Cordovaプラグインなどの)ライブラリプロジェクトにある場合は、context.getResources().getIdentifier(name, className, context.getPackageName());
を使用してリソースを取得できます。
これは、ライブラリプロジェクトのリソースRファイルが適切に生成されておらず、R packageNameがライブラリプロジェクトで必要なpackageNameと一致しない場合に発生します。
使い方はuser558185の回答と同じですが、ネイティブのAndroid=メソッドを使用します。
Eclipseを使用している場合は、プロジェクト"Properties->Java Build Path"
に移動します。タブ"Source"
で、パックするresフォルダーを追加します(例:res/raw)。
次の行を.classpath
ファイルに追加します
<classpathentry kind = "src" path = "res/raw" />
ビルドが完了すると、新しいjarファイルにはres/raw/
フォルダー内のファイルが含まれます。 ser558185 の提案に従ってそれらにアクセスできます。
抽象化を使用して、実装クラス(ユーザー)からR値を取得できます。
_protected abstract void getMyLayoutTextBox(int myLayoutTextBox);
_
次に、ユーザーはクラスを拡張し(Activity
を拡張)、このメソッドを実装する必要があります。クラスでは、getMyLayoutTextBox()
を呼び出すだけで、ユーザーが配布可能なjarを実装した後、ユーザーから正しいR値が提供されます。
ここの抽象化 についての詳細を読むことができます。