在可分发的Jar文件中打包Android资源文件

时间:2010-01-03 13:45:09

标签: android android-resources

我正在开发一些可重复使用的Android代码,我希望将其分发给其他开发人员,以便在他们自己的应用程序中使用。代码有一些资源依赖(layouts,xml和png drawables),我希望能够在单个包(Jar文件)中包含和引用。

这可能,如果是这样,最好的方法是什么?

9 个答案:

答案 0 :(得分:54)

由于Android会自动使用R文件夹下的资源文件生成/res类,因此使用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. 构建

答案 1 :(得分:26)

我没有任何乐观的消息。一般而言,您无法像预期的那样轻松地分发自己的包。主要问题是自动生成的R文件。你可能会对它做一些引用 - 你有你的布局和drawables。您图书馆的用户将拥有自己的R文件 - 包含其资源的ID,而不是您的图书馆提供的资源。

在可绘制资源的情况下,您可以以经典方式阅读它们,而无需R文件。但据我所知,您无法从外部xml文件中扩充布局。

所以这里丑陋的黑客就是将你的库与你的所有资源一起分发,用户必须将其复制到他的“res”文件夹。说实话,你的问题没有很好的解决方案......对不起。 此致!

答案 2 :(得分:19)


布局:

java源代码中的硬代码


xml&amp; png:

复制xml&amp; 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);

答案 3 :(得分:4)

我刚刚发现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 :(得分:3)

您可以使用android方法动态获取资源ID。

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

稍后您的资源必须包含(复制)到您的新项目中。

答案 5 :(得分:1)

我正在使用user558185解决方案,但这是一种更简单的方法。如果您的资源位于库项目中(例如,对于Cordova插件),您可以使用context.getResources().getIdentifier(name, className, context.getPackageName());获取资源

当库项目资源R文件未正确生成且R packageName与库项目所需的packageName不匹配时,会发生这种情况。

用法与user558185答案相同,但它使用原生Android方法。

答案 6 :(得分:1)

嗨,我认为这是一个迟到的回复,但我仍然只是通知AAR

Android ARchive - 此文件可以保存您的res和清单文件,以便其他开发人员可以将aar导入其项目并编译其代码。

这样我们可能会收到Manifest合并错误,修复它在清单中使用replace属性,这应该在分发之前进行检查。

答案 7 :(得分:0)

您可以使用抽象来从实现类(用户)获取R值。

protected abstract void getMyLayoutTextBox(int myLayoutTextBox);

然后,用户必须扩展您的类(扩展Activity),并实现此方法。在你的课堂上,你只需要调用getMyLayoutTextBox(),你就可以在用户实现可分发的jar后提供正确的R值。

您可以阅读有关abstraction here的更多信息。

答案 8 :(得分:0)

如果您使用的是Eclipse,请转到项目"Properties->Java Build Path"。在标签"Source"下,添加要包装的res文件夹(例如res / raw)

它会将以下行添加到.classpath文件中     &lt; classpathentry kind =&#34; src&#34;路径=&#34; RES /原料&#34; /&GT;

构建完成后,新的jar文件将包含res/raw/文件夹中的文件。您可以按建议的user558185访问它们。