Java Question Accessing R.java

barx

Well-Known Member
Licensed User
Just a quick question. Is there an easy way to access R.java when creating a lib. I found what I think is a way to do it in another lib but it requires quite a few lines of code. Was just wondering if there was something simple I'm missing.

Regards
 

warwound

Expert
Licensed User
corwin42's AHQuickAction library contains a very useful class named RHelper which makes it easy to get resources from the dynamically compiled R class.

That is as long as your library user has added read-only resources to their project.

I copied and used it for the first time just earlier today and it works perfectly (just testing a library on my computer) so i made a note to contact corwin42 to ask if it's allowed to copy that class for my own use.

I have some other code that i was gonna ask corwin42 about so haven't got in touch with him yet but that looks like the best and most reliable way to access the R class from a library...

Who shall ask permission first you or i? :cool:

Martin.
 

barx

Well-Known Member
Licensed User
R.java is only created during compilation, therefore you cannot directly access it from your library code by using R.xxxx.

Ah yes, that explains that then.

Thanks
 

barx

Well-Known Member
Licensed User
corwin42's AHQuickAction library contains a very useful class named RHelper which makes it easy to get resources from the dynamically compiled R class.

That is as long as your library user has added read-only resources to their project.

I copied and used it for the first time just earlier today and it works perfectly (just testing a library on my computer) so i made a note to contact corwin42 to ask if it's allowed to copy that class for my own use.

I have some other code that i was gonna ask corwin42 about so haven't got in touch with him yet but that looks like the best and most reliable way to access the R class from a library...

Who shall ask permission first you or i? :cool:

Martin.

Thanks the 'way' I found too. just hope he doesn't mind us borrowing it ;)

Please Mr corwin
 

barx

Well-Known Member
Licensed User
obviously I'm still very new to this but isn't this an example for retrieving a value from R.java?

B4X:
BA.applicationContext.getResources().getIdentifier(s, "drawable", BA.packageName)
 

warwound

Expert
Licensed User
I have just sent corwin42 a PM asking for permission to use his RHelper class.

I also included a link to this thread so as soon as he decides whether or not we can use RHelper then we'll be able to take a step forward.

Martin.
 

barx

Well-Known Member
Licensed User
:sign0098:
 

barx

Well-Known Member
Licensed User
OK If my findings are correct this could well help a few people out (warwound).

I made a quick and dirty test library with the following 2 methods

B4X:
   public int getRJavab4a(BA ba)
   {
      int returnId;
      returnId = BA.applicationContext.getResources().getIdentifier("icon", "drawable", BA.packageName);
      
      return returnId;
   }
   
   public int getRJavacorwin()
   {
      int returnId;
      returnId = getResourceId("drawable", "icon");
      
      return returnId;
   }

This was to see if, as I posted above, the BA statement above could be used to get values from the R.Java as required. As you can see the first method uses BA, the second uses the aforementioned 'corwin42' class code. corwin42's code was in the library but not show here in case he isn't happy it being public.

I passed the same params in the lib for ease and then made a new b4a project with the following code.

B4X:
Sub Globals
   Dim rj As RJavaChecker
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Log("b4a method - " & rj.getRJavab4a)
   Log("corwin Method - " & rj.RJavacorwin)
End Sub

The results, as I suspected (and hoped) are as follows.

B4X:
LogCat connected to: emulator-5554
** Activity (main) Create, isFirst = true **
b4a method - 2130837504
corwin Method - 2130837504
** Activity (main) Resume **

So as you can see; Yes they do the same thing. Please, somebody correct me if I'm wrong.

Regards
 

corwin42

Expert
Licensed User
Sorry for late answer but I was busy with my family the last days.

JD-Gui seems to be the most used tool of all B4A library developers :)

I will explain the history behind the RHelper class. I got the idea when I have seen Erels nine patch images tutorial. This was the first time I have seen that it was possible to access the Android Resource files from within B4A. It was clear, when it is possible to access them from B4A it should be also possible to access them from within a library.
Because in the tutorial Erel used reflection to access the IDs I tried this approach in the AHActionBar library, too, and it worked very well.
I think I even borrowed the GetStaticField method from agrahams Reflection library. But If you google for "accessing static field with reflection" you will find hundreds quite similar solutions. I have changed my code a few days ago to a recursive approach so it isn't a copy of agrahams code anymore.

Overall I think the whole solution is not magic and is quite simple. So I don't mind if you copy it from me. An even better solution seems to be the approach from barx with the static BA.applicationContext field. The result should be the same.

If anybody wants to copy a part of my libraries, just do it. You don't need to ask for it. The only exception where you should ask is if you copy the whole library, make some minor changes and then want to release it again. In this case I think it is better if you ask me to merge your changes into my original library.

Attached is the latest version of the RHelper class but I think I should change it again to the BA.applicationContext version.
 

Attachments

  • RHelper.zip
    594 bytes · Views: 231

barx

Well-Known Member
Licensed User
Thanks for the reply corwin42. Good to know we are part of a sharing community.
 

agraham

Expert
Licensed User
I have changed my code a few days ago to a recursive approach
Reflection is slow anyway but using exceptions is a very expensive way of accessing any superclass fields/methods. If you know the field is public then getField() is the most efficient otherwise a you need to do a proper loop on getDeclaredField().
 

warwound

Expert
Licensed User
Well i've decided to use Barx's quick and simple solution:

B4X:
BA.applicationContext.getResources().getIdentifier("balloon_overlay", "layout", BA.packageName)

It works perfectly :sign0098:!

Martin.
 

Roger Garstang

Well-Known Member
Licensed User
Trying this out and can't seem to get access to my 9 Patch images in the B4A files folder with:

B4X:
public Drawable GetBackgroundResource(String ImageName) {
       return BA.applicationContext.getResources().getDrawable(BA.applicationContext.getResources().getIdentifier(ImageName, ".R$drawable", BA.packageName));
    }

or

B4X:
public Drawable GetBackgroundResource(String ImageName) {
       return BA.applicationContext.getResources().getDrawable(BA.applicationContext.getResources().getIdentifier(ImageName, "drawable", BA.packageName));
    }

What is the correct way to get these? I either get a resource not found exception (ID returned is 0), or the app Force Closes.
 

warwound

Expert
Licensed User
I'd say first check that your project is being compiled with the resources that you want to access.
Run your project and then look in the Objects/gen/package_name/ folder, open R.java in a text editor.

Can you see references to the drawables you are expecting to be available?

Martin.
 

Roger Garstang

Well-Known Member
Licensed User
The resources aren't in the Java Project (It is my understanding that needs the this.getClass().getResourceAsStream() stuff Erel mentions in another thread...I may end up using that if I can't get this to work, but would then need information on how to get a 9 Patch Drawable out of that). I have the resources in the B4A Project's Files folder. They are Nine Patch images I use in another Activity, so know they are there. I'm trying to do something like the Reflection 9 Patch code does and assign the background to my views. In another function in my Library I pass a View and a Background Object in that is either a Color Int or Drawable and set the Background with

B4X:
if (Background instanceof Drawable) viewList.get(viewName).setBackground((Drawable) Background);

But, I can't even get to that point as the code in the previous post fails.
 

Roger Garstang

Well-Known Member
Licensed User
Ok, it appears to not like the 9 Patch image when getting the Drawable. I switched it to:

B4X:
public Integer GetBackgroundResourceID(String ImageName) {
       return BA.applicationContext.getResources().getIdentifier(ImageName, "drawable", BA.packageName);
}

and set it with:

B4X:
if (BackgroundResourceID != 0) {
         viewList.get(viewName).setBackgroundResource(BackgroundResourceID);
}

And, it works. So, I lost my ability to also pass a Color by making it the ID since both are Int. I'm guessing B4A can't/won't support polymorphism with the way the IDE has to use the XML to know what our methods are and it doesn't support it in the IDE. Color was kind of dumb anyway and very limited, so this works I guess unless there is a better way to get a drawable that can get 9 Patch too.
 
Top