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

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

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

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

在可绘制的资源的情况下,你可以阅读经典的方式,没有R文件。 但据我所知,你不能从外部XML文件充气布局。

所以这里的丑陋的黑客就是将你的图书馆和你的所有资源一起分发,这些用户将不得不复制到他的“res”文件夹中。 说实话,没有很好的解决scheme,你的问题…对不起。 问候!

由于Android会自动使用/res文件夹下的/res文件生成R类,所以使用R类作为final static是不可能的。

我发现一个很好的解决scheme,使用res文件的jar文件。 我是这样做的:

  1. 在你的源代码中将被导出的jar文件中, 不要使用 Rvariables,因为它将在编译时被replace为最终的静态内存地址。 而不是使用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"); 

    如果你有一个string的id是“text1”,你可以通过调用方法来获取它

     int id = getResourceIdByName(context.getPackageName(), "string", "text1"); 

    此方法在运行时为您提供资源ID。 它使用reflectionAPI在运行时获取R的状态。

    通过使用这种方法,你可以避免使用Rvariables。

  2. 将您的res文件复制到您的目标项目。

  3. build立。


布局:

在您的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. 

这听起来很有希望,虽然我还没有尝试过,所以我没有线索,如果它的工作。 我怀疑这是为了解决@JJKim的post所述的问题。

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

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

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

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

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

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

嗨,我认为这是一个迟到的反应,但我仍然只是通知有关AAR

Android ARchive – 这个文件可以保存你的res和manifest文件,这样其他开发者只需将aar导入他们的项目并编译他们的代码。

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

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

 protected abstract void getMyLayoutTextBox(int myLayoutTextBox); 

然后用户必须扩展你的类(它扩展了Activity ),并实现这个方法。 在你的类中,你只需调用getMyLayoutTextBox()并且在实现了可分发的jar之后,你将得到用户提供的正确的R值。

你可以在这里阅读更多关于抽象的知识 。

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

它会将下列行添加到.classpath文件中
<classpathentry kind =“src”path =“res / raw”/>

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