I have an Android project that I'm trying to make into a library. I get an exception thrown on this code:
_buttonStart = (Button) findViewById(R.id.buttonStart);
The exception I get is:
java.lang.NoSuchFieldError: com.xxx.libraryname.R$id.buttonStart
The Android docs seem to explicitly say that the library should be able to access those resources:
"For example, source code in the library project can access its own resources through its R class."
When I look in the library's /gen/com.xxx.libraryname/R.java/R/id/, buttonStart is there. But when I look in the main project's /gen/com.xxx.libraryname/R.java/R/id, it isn't.
I've done a make clean.
Your library project also has same name layout main.xml as your main project.
Android will give priority to host project if both have the same Layout name, in this case "main.xml" Best approach is to use some prefix notation so there are no accidental collisions.
Related
I have:
one Main App
one Android Library Project with a Fonts in it in "assets/fonts/Old_English.ttf
The Main App references the Android Library Project and it works fine except the following:
I would like the use the shared asset resource, but I don't know how to do. Can someone help ?
Typeface.createFromAsset(getAssets(), "fonts/Old English.ttf")
These might work:
Storing and accessing assets.
library structure
MyLibProject/src/main/assets/Old_English.ttf
Project Reference
Typeface.createFromAsset("file:///android_asset/Old_English.ttf");
The solution is as per the link mentioned. I didn't try its working. Please comment if it works or not.
Make sure that you store your fonts according to the following structure :
Now use the following line :
Typeface typeface=Typeface.createFromAsset(getApplicationContext().getAssets(), "fonts/Old_English.ttf");
I have been looking through the android source code for ICS and JB (API15 & API16) and am finding what appears (to me) to be a mismatch between the code and the jar files. More specifically, in SpeechRecognizer.java there is a reference to Settings.Secure.VOICE_RECOGNITION_SERVICE, which is defined in android/provider/Settings.java under the subclass Secure as
public static final String VOICE_RECOGNITION_SERVICE = "voice_recognition_service";
But when I try to reference VOICE_RECOGNITION_SERVICE from my own code, it cannot be resolved. In Eclipse, when I look through the jar file, I do not see VOICE_RECOGNITION_SERVICE defined. In fact, many of the fields in Settings.Secure which are defined as public in the java source code are not found in the jar file. I am wondering why, if the jar file was created using the source files, I cannot access VOICE_RECOGNITION_SERVICE. If a field is declared public in the source then shouldn't it be accessible from the .jar file?
I noticed the same. It seems that often, some of the methods/fields are not visible for application-specific code.
However, sometimes it is possible to invoke these methods/fields by using Java reflections.
I have an Android library MyLib containing everything I need for my app (targeting Android 2.2). This library has an XML resource:
drawable/main_background.xml
In my Application MyApp project I reference MyLib. Here I want to override specific resources (i.e. branding). So I added a background image in MyApp:
drawable/main_background.png
Eclipse keeps giving me this error:
[com.mycom.mylib.myapp] res\drawable\main_background.xml:0: error: Resource entry main_background is already defined.
[com.mycom.mylib.myapp] res\drawable\main_background.png:0: Originally defined here.
How can I override the resource in the library project?
You cannot simply override resource ID (it's the resource ID you are overriding, not the actual file) with a file with different extension in Android SDK. However, you can do the trick by putting in your project xml file with the same name (main_background.xml) and fill it in a proper way to display your new file (main_background.png), which you need to rename earlier. All syntax you need is descibed here:
http://developer.android.com/guide/topics/resources/drawable-resource.html
, in your case it could be simply (assuming you put this in your non-library project as main_background.xml, and you have your new png as main_background_new.png):
<?xml version="1.0" encoding="utf-8"?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/main_background_new" />
With above solution, you could refer to #drawable/main_background from your project and it should use your file included with that project, instead of a library one.
[com.mycom.mylib.myapp] res\drawable\main_background.xml:0: error: Resource entry main_background is already defined.
[com.mycom.mylib.myapp] res\drawable\main_background.png:0: Originally defined here.
I don't believe you can have the same file name even with different extensions. Try naming the png something else.
Now, i've not used overriding, So this seems odd as you'd expect this to be how you override the asset. However i think you've either got the two assets in your lib named the same. And that in your project it might be ok to have an asset with the same name. I would however check that its ok to have different types. XML is different than png, and if you access the asset from code you could get type errors.
Let me clarify the above point. I understand that a library project can have an item with the same Resource ID as an item in your application.
However the error above suggests that both main_background.png and main_background.xml are in the same project ([com.mycom.mylib.myapp]) which i don't believe is correct.
Further reading
This page describes the various types of project including the library project http://developer.android.com/tools/projects/index.html
Now i don't know where i got the impression from but having looked again it simply doesn't state anywhere that you can override a resource by using the same resource name. God knows why i thought that was a feature.
So no, the same rule applies as far as i can tell, that resources have to be named uniquely even across library projects, otherwise the generated resource ids will conflict. (The error your getting)
What is explained is how resource conflicts are managed.
Resource conflicts Since the tools merge the resources of a library
project with those of a dependent application project, a given
resource ID might be defined in both projects. In this case, the tools
select the resource from the application, or the library with highest
priority, and discard the other resource. As you develop your
applications, be aware that common resource IDs are likely to be
defined in more than one project and will be merged, with the resource
from the application or highest-priority library taking precedence.
The system will use the resource with the highest priority, discarding everything else. Whats odd, is that you would think that a compile error wouldn't occur as the compiler should be discarding the resource. This makes me believe that the original poster had the similarly named assets in the same project, and not across the lib and project.
I haven't read anywhere that this is actually an intended feature. Got any links to say otherwise? (comment them)
So one 'solution' to this problem, which I do not consider to be an answer is the following:
Define an XML document in the library in question (we'll call it bunny.xml), and have it refer to another xml of a similar name (bunny_drawn.xml) with the actual content to be displayed.
Then, in the target project, override bunny.xml with another and use it to refer to an image with a different name instead - bunny_image.png
This does not however solve the problem, firstly because we aren't technically overriding a png with an xml (although the effect is somewhat close to that). Secondly because one of the key features of overriding resources is they are overridden, i.e. they are NOT compiled into the APK:
the tools ensure that the resource declared in the application gets
priority and that the resource in the library project is not compiled
into the application .apk
But the bunny_drawn.xml will still be compiled in! We can sort-of overcome the second point, by not only defining the image to be replaced in the target APP, but also replacing the old target bunny_drawn.xml with a blank xml. (or, as Fenix pointed out, you can have the contents of bunny_drawn.xml inside bunny.xml in the first case - the fact still remains that the resource ID can't be replaced...)
So my final conclusion is that this need to be submitted as a bug in the Developer Tools.
My application depends on a library project.
The menu.xml file is within the application project.
All the java code is within the library project, including the menu handler code onOptionsItemSelected().
Is there a way to access the application resources from library project ? I'd like to write something like this, which is currently impossible, since menu items are not visible from the library:
if ( item.getItemId()==R.id.settings ) {
...
}
Yes you can if you know the package name of your library. See: Resources#getIdentifier
You can do:
getResources().getIdentifier("res_name", "res_type", "com.library.package");
ex:
R.id.settings would be:
getResources().getIdentifier("settings", "id", "com.library.package");
You should really just include a version of the menu.xml resource in your library project. If you want to have a different menu.xml in your application, you can do that and it will override the copy from the library project.
From the Library Projects docs:
In cases where a resource ID is defined in both the application and the library, the tools ensure that the resource declared in the application gets priority and that the resource in the library project is not compiled into the application .apk. This gives your application the flexibility to either use or redefine any resource behaviors or values that are defined in any library.
I found #triad's solution with Resources.getIdentifier(String, String, String) to be somewhat error-prone:
the String-literal resource identifiers aren't checked by the IDE
multiple sequential String arguments to a single method are easy to use incorrectly.
I found this approach to work better for me:
String libString = context.getString(example.library.pkg.R.string.library_string)
Where the library's package is example.library.pkg.
The library's R class is resolved at compile-time, so your IDE will tell you if you referenced it correctly
Not importing the library's R class allows you to still use your own local R later,
and explicitly marking the external resource usages makes them easier to spot.
The library project looks fine, but as soon as I import it to my main project, it shows me errors on each line which is referencing a resource:
id cannot be resolved or is not a field
The main project shows no errors.
Of cause I ask myself where android knows where to import the resources from e.g. in lines like that:
RelativeLayout menuLayout = (RelativeLayout) this.findViewById(R.id.menu_layout);
But this works neither:
RelativeLayout menuLayout = (RelativeLayout) this.findViewById(net.bla.library.R.id.menu_layout);
Any Ideas?
EDIT: what I found out is:
As soon as I include the library project, Eclipse duplicates the gen/net.mylibrary.R from the library into the main app (so there are 2 packages in the gen folder now: the one from the app, and the copied one from the library). strange thing is: R.id is not found in the copy. There are some other differences too, like the copy uses an additional "final" for its definitions.
I really have no clue why this might happen. Someone?
Eclipse sometimes likes to import android.R, and this causes errors similar with you are experiencing.
Look for the import at the top of the file, and remove it.
As it's stated on "Using Eclipse | Android Open Source":
Note: Eclipse sometimes likes to add an import android.R statement at the top of your files that use resources, especially when you ask eclipse to sort or otherwise manage imports. This will cause your make to break. Look out for these erroneous import statements and delete them.
I had a similar problem and I managed to resolve it.
Here is what I did:
When I call the main activity of my library project, the activity's onCreate method calls setContentView method and uses R.layout.main as a parameter.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
Button btn = (Button) findViewById(R.id.main_button1);
btn.setOnClickListener(this);
findViewById returned null.
It seems that main.xml of the library project is being overriden by the main project's main.xml.
So I simply created a new xml layout main_libname.xml with the same content as library's main.xml and used this layout as a parameter for setContentView.
It did work!
Check out if the resources are inside the res folder. All the resources must be inside.
0 Proyect
0.1 src
0.2 res
0.2.1 layout
0.2.1.1 main.xml
0.2.1.2 menu_layout.xml
0.2.2 drawables
.....
Maybe you are putting the data in project folder.
I was also having the "cannot find symbol variable ..." error on a R.id item defined in a library project. Notably, only R.id symbols were not resolvable in the main project even though the other R fields (eg. R.layout) were clearly visible.
Fortunately, I was able to stumble upon on a solution. It turned out that in my case, I had a resource (a layout file) defined in my main project which had exactly the same name as that in the library project.
This was what this looked like filesystem-wise:
top_level_project
main_android_proj
src
main
res
layout
activity_main.xml
android_library_subproject
src
main
res
layout
activity_main.xml
My sub-project's activity_main.xml had an id like so:
<RelativeLayout....>
<TextView android:id="#+id/special_text" ... />
</RelativeLayout>
And this is how I try to reference the id in my main project's java code:
MainActivity.java:
public void onCreate() {
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.special_text);
tv.setText("Hello Android");
}
To fix this issue, I renamed the offending file in my main project to something else.
It seems that you can't have duplicate layout names in your resources.
Indeed, the sdk docs do point out that you should be careful with resource name conflicts when using library projects:
Resource conflicts
Since the tools merge the resources of a library
project with those of a dependent application project, a given
resource ID might be defined in both projects. In this case, the tools
select the resource from the application, or the library with highest
priority, and discard the other resource. As you develop your
applications, be aware that common resource IDs are likely to be
defined in more than one project and will be merged, with the resource
from the application or highest-priority library taking precedence.