在可分发的 Jar 文件中打包 Android 资源文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1995004/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Packaging Android resource files within a distributable Jar file
提问by Jeff Gilfelt
I am working on some reusable Android code that I would like to distribute to other developers for use within their own applications. The code has some resource dependencies (layouts, xml & png drawables) that I would like to be able to include and reference within a single package (Jar file).
我正在研究一些可重用的 Android 代码,我想将这些代码分发给其他开发人员,以便在他们自己的应用程序中使用。该代码具有一些资源依赖项(布局、xml 和 png 可绘制对象),我希望能够在单个包(Jar 文件)中包含和引用这些资源。
Is this possible, and if so what is the best method to do this?
这是可能的,如果是这样,最好的方法是什么?
采纳答案by Ramps
I don't have any optimistic news for you. In general you cannot distribute your own package as easily as you would expect. The main problem is the autogenerated R file. You probably make some references to it - you have your layouts and drawables. User of your library will have his own R file - containing ids for his resources, not for the ones your library provides.
我没有什么好消息要告诉你。通常,您无法像预期的那样轻松分发自己的软件包。主要问题是自动生成的 R 文件。您可能对它进行了一些参考 - 您有自己的布局和可绘制对象。您图书馆的用户将拥有他自己的 R 文件 - 包含他的资源的 ID,而不是您的图书馆提供的资源。
In case of drawable resources you could read them in classic way, without R file. But as far as I know you are not able to inflate layouts from external xml files.
对于可绘制资源,您可以以经典方式读取它们,而无需 R 文件。但据我所知,您无法从外部 xml 文件中扩展布局。
So the ugly hack here would be to distribute your library together with all your resources, which user would have to copy to his "res" folder. To be honest, there is no good solution to your problem... sorry. Regards!
因此,这里的丑陋技巧是将您的库与所有资源一起分发,用户必须将其复制到他的“res”文件夹中。老实说,您的问题没有好的解决方案......抱歉。问候!
回答by J.J. Kim
Since Android makes the R
class automatically with resource files under the /res
folder, using the R
class as final static
is impossible.
由于AndroidR
自动使用文件/res
夹下的资源文件创建R
类,final static
因此无法使用该类。
I found a nice solution to use a jar
file with the res
files. Here is how I did it:
我找到了一个很好的解决方案来将jar
文件与文件一起使用res
。这是我如何做到的:
In your source code which will be exported in the
jar
file, don't useR
variable because it will be replaced with a final static memory address in compile time. Instead of usingR
, I made my own method below: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; }
For example, if you have a layout named
main.xml
, you can get it by calling the method:int id = getResourceIdByName(context.getPackageName(), "layout", "main");
If you have a string whose
id
is "text1", you can get it by calling methodint id = getResourceIdByName(context.getPackageName(), "string", "text1");
This method gives you your resource id at runtime. It uses the reflection API to get the status of
R
at runtime.By using this method you can avoid using the
R
variable.Copy your
res
files to your target project.Build.
在将导出到
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
文件复制到目标项目。建造。
回答by user558185
layouts:
布局:
hard code in your java source
java源代码中的硬代码
xml & png:
xml & png:
copy xml & png to your project src folder and package to jar, for example
例如,将 xml & png 复制到您的项目 src 文件夹并打包到 jar
copy a.png to src/com/example/test
将 a.png 复制到 src/com/example/test
load it as following java codes:
将其加载为以下 java 代码:
InputStream is = YourClassName.class.getClassLoader().getResourceAsStream("com/example/test/a.png");
if ( null != is )
{
Bitmap bmp = BitmapFactory.decodeStream(is);
回答by scorpiodawg
I just found that the aapt
tool in the Android SDK allows the following option:
我刚刚发现aapt
Android 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.
--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.
This sounds promising, though I have not tried this so I haven't a clue if it works. I suspect this is to get around the problem addressed by @J.J.Kim's post above.
这听起来很有希望,但我还没有尝试过,所以我不知道它是否有效。我怀疑这是为了解决上面@JJKim 的帖子所解决的问题。
回答by Konrad Nowicki
You can dynamically get resource id using android method.
您可以使用 android 方法动态获取资源 ID。
int preferences = context.getResources().getIdentifier("preferences", "xml", context.getPackageName());
Later your resources have to be included (copied) to your new project.
稍后您的资源必须包含(复制)到您的新项目中。
回答by Hugo Gresse
I was using user558185solution but here is a more simple way. If you resources is in a library project (for a Cordova Plugin for example), you can get resource with context.getResources().getIdentifier(name, className, context.getPackageName());
我使用的是user558185解决方案,但这里有一个更简单的方法。如果您的资源位于库项目中(例如 Cordova 插件),您可以使用context.getResources().getIdentifier(name, className, context.getPackageName());
This happen when the library project resources R file is not generated properly and the R packageName did not match the required packageName by the library project.
当库项目资源 R 文件未正确生成并且 R packageName 与库项目所需的 packageName 不匹配时,会发生这种情况。
The usage is the same as user558185 answer, but it use a native Android method.
用法与 user558185 answer 相同,但它使用原生 Android 方法。
回答by Vimalanathan
Hi i think this is a late response but still i just what to inform about AAR
嗨,我认为这是一个迟到的回复,但我仍然只是要告知有关 AAR 的信息
Android ARchive - this file can hold your res and manifest files, so that the other develop can just import the aar to their project and compile their code.
Android ARchive - 该文件可以保存您的 res 和 manifest 文件,以便其他开发人员可以将 aar 导入他们的项目并编译他们的代码。
This way we might get Manifest merge errors, the fix for it to use replace property in your manifest and this should be checked before distribution.
这样我们可能会得到清单合并错误,修复它在清单中使用替换属性,这应该在分发前检查。
回答by june232
If you are using Eclipse, go to project "Properties->Java Build Path"
. Under tab "Source"
, add the res folder you want to pack (e.g. res/raw).
如果您使用的是 Eclipse,请转到 project "Properties->Java Build Path"
。在 tab 下"Source"
,添加要打包的 res 文件夹(例如 res/raw)。
It will add the following line into the .classpath
file
<classpathentry kind="src" path="res/raw"/>
它将将以下行添加到.classpath
文件
<classpathentry kind="src" path="res/raw"/>
After building done, the new jar file will contain the files in res/raw/
folder. You can access them as user558185suggested.
构建完成后,新的 jar 文件将包含文件res/raw/
夹中的文件。您可以按照user558185 的建议访问它们。
回答by CrackerHyman9
you can use abstraction to get the R values from the implementing class (the user).
您可以使用抽象从实现类(用户)获取 R 值。
protected abstract void getMyLayoutTextBox(int myLayoutTextBox);
Then the user has to extend your class (which extends Activity
), and implement this method. In your class, you just call getMyLayoutTextBox()
and you'll have the correct R value supplied by the user after he implements your distributable jar.
然后用户必须扩展您的类(即 extends Activity
),并实现此方法。在您的课程中,您只需调用getMyLayoutTextBox()
,在用户实现您的可分发 jar 后,您就会获得用户提供的正确 R 值。
You can read more about abstraction here.