Packaging Android resource files within a distributable Jar file
Since Android makes the R
class automatically with resource files under the /res
folder, using the R
class as final static
is impossible.
I found a nice solution to use a jar
file with the res
files. Here is how I did it:
-
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.
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.
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.
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!
layouts:
hard code in your java source
xml & png:
copy xml & png to your project src folder and package to jar, for example
copy a.png to src/com/example/test
load it as following java codes:
InputStream is = YourClassName.class.getClassLoader().getResourceAsStream("com/example/test/a.png");
if ( null != is )
{
Bitmap bmp = BitmapFactory.decodeStream(is);
I just found that the aapt
tool in the Android SDK allows the following option:
--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.