Tool R Class Generator [Library Development Tool]

Discussion in 'Additional libraries, classes and official updates' started by thedesolatesoul, Feb 16, 2015.

  1. thedesolatesoul

    thedesolatesoul Expert Licensed User

    What is it?
    This is a tool to automatically generate a B4A-type R class (in java) when developing libraries.

    This is NOT required for any B4A use code.
    This is NOT a requirement for library generation.

    This is only required for a particular methodology of library wrapping. It allows you to access resource files from within the library without packaging it yet.

    How was it built?
    This is a python script turned to an .exe in pyinstaller.

    How to run it?
    Run this in the folder with the base class of the source you are trying to wrap. It doesnt really matter where you run it from, it will recursively go through every subfolder and analyze any .java files found in those folders.

    What does it generate?
    It will generate the file in the same folder as itself.
    The R class will have the following format (you will need to add the imports).

    public class R {
    public static final class color {
    public static int material_drawer_selected_text = BA.applicationContext.getResources().getIdentifier("material_drawer_selected_text""color", BA.packageName);
    public static int material_drawer_secondary_text = BA.applicationContext.getResources().getIdentifier("material_drawer_secondary_text""color", BA.packageName);
            public static final class dimen {
                    public static int material_drawer_margin = BA.applicationContext.getResources().getIdentifier("material_drawer_margin", "dimen", BA.packageName);
                    public static int material_drawer_margin = BA.applicationContext.getResources().getIdentifier("material_drawer_margin", "dimen", BA.packageName);
            public static final class string {
                    public static int drawer_close = BA.applicationContext.getResources().getIdentifier("drawer_close", "string", BA.packageName);
            public static final class id {
                    public static int icon = BA.applicationContext.getResources().getIdentifier("icon", "id", BA.packageName);
                    public static int name = BA.applicationContext.getResources().getIdentifier("name", "id", BA.packageName);

    By embedding the file in your library you will be able to access resources added using #AdditionalRes.

    It generates a lot of duplicate identifiers.
    Havent really tested it in a real library.

    RGenerator Version 1:

    @warwound for identifying this method of accessing resources.
    Last edited: Mar 16, 2015
  2. omidaghakhani1368

    omidaghakhani1368 Well-Known Member Licensed User

    You are wonderfull
  3. DonManfred

    DonManfred Expert Licensed User

    Sounds interesting! Will try that in a future wrapping project :)

    Thank you for sharing!
  4. thedesolatesoul

    thedesolatesoul Expert Licensed User

    I used to try to get the library working without the extra resources (usually loaded on init or a constructor).
    Later I realized its easier to generate an R class and just load the AdditionalRes.
    Johan Schoeman, NJDude and DonManfred like this.
  5. DonManfred

    DonManfred Expert Licensed User

    I´m sure the tool will help me in future library wrappings..
    I just run a test

    R class looks good!

    Again thank you for sharing!
    thedesolatesoul likes this.
  6. DonManfred

    DonManfred Expert Licensed User

    Honestly i dont know whether it works lol

    But all what i have expected were available in the class :)
  7. thedesolatesoul

    thedesolatesoul Expert Licensed User

    I used it yesterday, and it did miss a couple of identifiers. Also it added duplicates (I can fix this).
    So its buggy but a lot better than starting from scratch.
    NJDude likes this.
  8. corwin42

    corwin42 Expert Licensed User

    Hmm, since we have the #AdditionalRes keyword it isn't required to use such helper functions to get the resources like in the generated class.

    If a library needs resources just create it in Eclipse as an Android Project. Then copy all resources to the res folder of this project. The file will be generated automagically in the Eclipse project so it compiles and you can create the jar. Later in the B4A project you can add the resources with the #AdditionalRes keyword.

    See the AppCompat library. It is created this way.

    Erel explained how to wrap a library with resources here. Additionally to Erels method you can even join the wrapper library project and the project for the wrapped library together into one project.
    Last edited: Feb 17, 2015
    cimperia and thedesolatesoul like this.
  9. DonManfred

    DonManfred Expert Licensed User

    Then i´m doing somwhat wrong ALL THE TIME... Eclipse does not create a res-folder for me.
    BUT i dont use Eclipse to compile... I always use SLC for the compiling (i have included the SLC in Eclipse to compile directly from eclipse (with the SLC sure)

    When i try to wrap a library i always have the issue that in eclipse the r-file is missing and i need to rwrite all sources who depends on values from R class. For me this tool make sense...

    But probably i´m doing something wrong in Eclipse too ;)
  10. thedesolatesoul

    thedesolatesoul Expert Licensed User

    Thank you @corwin42 . I wasnt aware of that (or that tutorial).
    If I understand you correctly, I can just import it as an Android project. It will build a jar file, which I will take and reference in my library project.

    I guess then my tools isnt really needed but to be honest it gives you a pretty fast shortcut, as once you generate the, its a drag/drop into eclipse (with all the source .java).
    Peter Simpson and NJDude like this.
  11. thedesolatesoul

    thedesolatesoul Expert Licensed User

    It is because we use a 'Java project' for the wrapper, but its the 'Android project' that will have the res files etc. It requires ADT to be working correctly in eclipse.
    I might give it a shot sometime but considering i've already put in effort for this tool and it seems faster in my workflow I'll stick to it for now.
    Peter Simpson likes this.
  12. DonManfred

    DonManfred Expert Licensed User

    Suggestion for future Version:

    Could you please add
    import anywheresoftware.b4a.BA;
    per default in the R class?
  13. thedesolatesoul

    thedesolatesoul Expert Licensed User

    Will do.
    DonManfred and NJDude like this.
  14. thedesolatesoul

    thedesolatesoul Expert Licensed User

    I've uploaded RGenerator2.
    This is massively improved from version 1.
    - Can deal with multiple symbols on the same line
    - Removes any duplicates
    - Adds the BA import at the start

    Pretty much generated a flawless R file for me now.

    I did try the Android Project method, but it was so incredibly messy and error prone (that I ended up deleting my whole source! good thing i set up GitLab!), I prefer this method as it works in one shot.
  15. thedesolatesoul

    thedesolatesoul Expert Licensed User

    Just to add more information about R class generation.
    Sometimes the identifier is an array of resources, so it is an int[] instead of int. These are particularly used when loading the whole style attributes in one go, they are actually just an array of individual resources.
    The RGenerator obviously doesnt cope with these.

    There are three ways to cope with these but they are pretty raw:
    1. Add the res files to an Android project in Eclipse as @corwin42 mentioned above.
    2. Just add the res files as AdditionalRes to a B4A project. A compile will generate the full file in Object/gen. Its pretty hard coded so I am not sure if it will have conflicts later on with multiple libraries.
    3. Do it manually. Each entry in the array consists of a resource type and a counter.
    Johan Schoeman likes this.
  16. DonManfred

    DonManfred Expert Licensed User

    Can you drop an example for this?

    I have several librarywrapping-tryings where i stuck at such a point.
  17. thedesolatesoul

    thedesolatesoul Expert Licensed User

    Here is the best information I found on the subject:

    Which makes my Step2 kind of wrong.

    I know this is manual labour but this is how I think you would go about it:
    public static int civ_primary_color = ...
    public static int civ_secondary_color = ...

    public static int[] civ = {civ_primary, civ_secondary};
    The question is how do you figure out the order? I believe they will be in the same order defined in the attribute set or styleable.
    DonManfred likes this.
  18. DonManfred

    DonManfred Expert Licensed User

    Im not sure but i think the order does not matter cause most of the "original libs" (so far i seen them in wrappers i did and run into problems cause of exactly this (using complete STYLEABLE blocks)) are using the values "by name" and not "by order"

    Will try out the sample you posted on a project i actually get stuck about this issue.Will keep you informed

    Thank you for your snippet!
  19. DonManfred

    DonManfred Expert Licensed User

    I wrote a part of r class for a new wrapper. With you suggestion the command
    TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.WeekView, 00);
    does not show an error now. Not sure actully if it will work... Keep you updated
  20. thedesolatesoul

    thedesolatesoul Expert Licensed User

    I guess the problem is that it wont show an error, but you dont know which resource is which (as it is just an array of integers).
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice