48

我正在开发一些可重用的 Android 代码,我想将其分发给其他开发人员,以便在他们自己的应用程序中使用。该代码具有一些资源依赖项(布局、xml 和 png 可绘制对象),我希望能够在单个包(Jar 文件)中包含和引用这些资源依赖项。

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

4

9 回答 9

55

由于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。R它使用反射 API在运行时获取状态。

    通过使用这种方法,您可以避免使用R变量。

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

  3. 建造。

于 2011-08-19T05:45:23.367 回答
26

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

如果是可绘制资源,您可以以经典方式读取它们,无需 R 文件。但据我所知,您无法从外部 xml 文件中扩充布局。

因此,这里最丑陋的技巧是将您的库与您的所有资源一起分发,用户必须将其复制到他的“res”文件夹中。老实说,您的问题没有好的解决方案......对不起。问候!

于 2010-01-03T14:10:23.307 回答
20

布局:

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);
于 2010-12-30T10:56:00.210 回答
4

我刚刚发现aaptAndroid SDK 中的工具允许以下选项:

   --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 的帖子所解决的问题。

于 2012-04-27T21:57:58.203 回答
3

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

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

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

于 2012-09-27T11:51:27.480 回答
1

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

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

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

于 2015-04-10T15:22:21.790 回答
1

嗨,我认为这是一个迟到的回应,但我仍然只是要告知有关 AAR 的信息

Android ARchive - 这个文件可以保存你的 res 和 manifest 文件,以便其他开发人员可以将 aar 导入他们的项目并编译他们的代码。

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

于 2016-03-10T14:46:34.173 回答
0

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

protected abstract void getMyLayoutTextBox(int myLayoutTextBox);

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

您可以在此处阅读有关抽象的更多信息。

于 2011-08-19T14:12:21.863 回答
0

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

它将将以下行添加到.classpath文件
<classpathentry kind="src" path="res/raw"/>

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

于 2015-01-06T08:15:30.023 回答