web-dev-qa-db-ja.com

パッケージングAndroid配布可能なJarファイル内のリソースファイル

私はいくつかの再利用可能なAndroidコードを自分のアプリケーション内で使用するために他の開発者に配布したいと考えています。コードにはいくつかのリソース依存関係(レイアウト、xmlおよびpngドローアブル))があります。単一のパッケージ(Jarファイル)内に含めて参照できるようにする。

これは可能ですか?可能であれば、これを行うための最良の方法は何ですか?

47
Jeff Gilfelt

楽天的なニュースはありません。一般に、あなたが期待するほど簡単にあなた自身のパッケージを配布することはできません。主な問題は自動生成されたRファイルです。あなたはおそらくそれをいくつか参照しています-あなたはあなたのレイアウトとドローアブルを持っています。ライブラリのユーザーは自分のRファイルを持ちます-ライブラリが提供するものではなく、自分のリソースのIDを含みます。

ドローアブルリソースの場合、Rファイルなしで従来の方法で読み取ることができます。しかし、私が知る限り、外部のxmlファイルからレイアウトを拡張することはできません。

したがって、ここでの醜いハックは、ライブラリをすべてのリソースと一緒に配布することです。そのユーザーは、自分の "res"フォルダにコピーする必要があります。正直なところ、問題に対する適切な解決策はありません...すみません。よろしく!

26
Ramps

Androidは/resフォルダの下のリソースファイルを使用してRクラスを自動的に作成するため、Rクラスをfinal staticとして使用することは不可能です。

jarファイルでresファイルを使用するための素晴らしい解決策を見つけました。ここに私がそれをした方法があります:

  1. 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変数の使用を回避できます。

  2. resファイルをターゲットプロジェクトにコピーします。

  3. ビルド。

55
J.J. Kim

レイアウト:

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);
19
user558185

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の投稿で取り上げられている問題を回避するためだと思います。

4
scorpiodawg

Androidメソッドを使用して、リソースIDを動的に取得できます。

int preferences = context.getResources().getIdentifier("preferences", "xml", context.getPackageName());

後でリソースを新しいプロジェクトに含める(コピーする)必要があります。

3
Konrad Nowicki

こんにちはこれは遅い応答だと思いますが、それでも私はAARについて何を通知するべきかだけです

Android ARchive-このファイルにはresファイルとマニフェストファイルを保持できるため、他の開発者はaarをプロジェクトにインポートしてコードをコンパイルするだけです。

これにより、マニフェストマージエラーが発生する可能性があります。マニフェストでreplaceプロパティを使用するための修正であり、配布前に確認する必要があります。

1
Vimalanathan

私は ser558185 ソリューションを使用していましたが、これはより簡単な方法です。リソースが(Cordovaプラグインなどの)ライブラリプロジェクトにある場合は、context.getResources().getIdentifier(name, className, context.getPackageName());を使用してリソースを取得できます。

これは、ライブラリプロジェクトのリソースRファイルが適切に生成されておらず、R packageNameがライブラリプロジェクトで必要なpackageNameと一致しない場合に発生します。

使い方はuser558185の回答と同じですが、ネイティブのAndroid=メソッドを使用します。

1
Hugo Gresse

Eclipseを使用している場合は、プロジェクト"Properties->Java Build Path"に移動します。タブ"Source"で、パックするresフォルダーを追加します(例:res/raw)

次の行を.classpathファイルに追加します
<classpathentry kind = "src" path = "res/raw" />

ビルドが完了すると、新しいjarファイルにはres/raw/フォルダー内のファイルが含まれます。 ser558185 の提案に従ってそれらにアクセスできます。

0
june232

抽象化を使用して、実装クラス(ユーザー)からR値を取得できます。

_protected abstract void getMyLayoutTextBox(int myLayoutTextBox);
_

次に、ユーザーはクラスを拡張し(Activityを拡張)、このメソッドを実装する必要があります。クラスでは、getMyLayoutTextBox()を呼び出すだけで、ユーザーが配布可能なjarを実装した後、ユーザーから正しいR値が提供されます。

ここの抽象化 についての詳細を読むことができます。

0
CrackerJack9