Repository navigation
Using androidannotations fails in a library project #78
Description
Activity
Thank you for reporting this error!
It's the same stacktrace as issue #66, but it probably has a different cause.
The values of the view related annotations should be an int or an array of int (R ids). If not set, the annotations have a default value (-1), which means use the name of the element to determine the id.
The stacktrace shows that the annotation value returns
nullwhich is not supposed to be even possible.I don't know why this is happening, and I don't know how to reproduce it.
Therefore, it would help us a lot it you could create a small project that reproduces the error, with some instructions on how to reproduce it.
Could you also let us know the versions of Eclipse, Android plugin, Android SDK, AndroidAnnotations that you use ?
Thanks again!
The crash should now be fixed in the latest snapshot. This doesn't mean we fixed the problem, but it should stop crashing and issue warnings instead.
See the Snapshot repository. This snapshot should contain the fix.
If would be great if you could confirm that you now see warnings instead of a crash, and copy & paste the warnings :) .
I am using Eclipse Build id: 20110916-0149 (Indigo SR 1)
It is Android 2.2 Level 8 (not Google)
Android Development Toolkit Version: 16.0.1.v201112150204-238534
And the error was with the AndroidAnnotations snapshot you posted.Thanks ! I'll have a look ASAP.
Were you able to repro?
Got stuck into a time travelling trap :s .. Sorry, but not yet. Thursday I'll be spending the whole day on AndroidAnnotations, I'll be sure to use it then. Thanks again for providing that.
@brh : I looked at it today.
Here is the error I have :
In
com.aa.brh.impl.AAImplActivity, on the following code :@EActivity(R.layout.main) public class AAImplActivity extends Activity { // ... }
There's a Java compiler error on
R.layout.mainwhich saysThe value for annotation attribute EActivity.value must be a constant expression.That's because the generated fields of the R class are not final :
public final class R { public static final class attr { } public static final class drawable { public static int ic_launcher=0x7f020000; } public static final class id { public static int aabreak=0x7f050000; } public static final class layout { public static int main=0x7f030000; } public static final class string { public static int app_name=0x7f040001; public static int hello=0x7f040000; } }
The reason these fields are not final is because it's a library project. We talked about that in issue #20.
I thought this was supposed to happen only for Android 4.0 apps, but it seems to happen for any app built with the latest SDK.
The strange thing is that you reported an exception which I don't even have, because it doesn't even compile.
Can you try unchecking isLibrary in the Library project and then compiling it and it should succeed, then check back that it is a library project and I think you may get the exception then.
A possible workaround for this would be to allow strings (e.g.,
@EActivity("main")) and usegetIdentifierto lookup the ID at runtime.@brh I tried what you said. When you change a project from Android App to Android Library, the R file is not recreated until you change some resources or clean the project, so that's why you didn't get the error related to
R.layout.main.However, I couldn't reproduce your error. I tried many different things but it didn't show up.
One thing I know : to fix #66 (commit 08fbafa), we added a fix that takes care of the potential NullPointerException, so you should not have the exception, and instead it should be a warning.
We released the 2.4 version yesterday (2.3 skipped, error at release time :) ) , could you please tell us if you still see the exception in the logs ? Do you get the warning instead ?
Anyway, I think the real issue here is how to handle the non final fields of the R class.
@JakeWharton
@EActivity("main")is a shortcut for@EActivity(value="main"). Thevalue()parameter of the@EActivityis actually already used, and it's anint(R.layout.someLayoutis anint). I'm willing to have support for lib projects but not at all costs :) .However, we could add another parameter, which would work as an alternate way to define the value. For example,
@EActivity(alt="main")or@EActivity(layout="main")We don't need to use
getIdentifier(), because once we know the name of the field at compile time, we can reference it in the generated code. The Android guys removed thefinalkeyword because they thought it would not harm anyone. There is a side effect that they didn't see : some frameworks use ids in annotations (we do, RoboGuice does), and annotations values need to be final.Another idea I had : we could generate an
R_class that would be a copy of theRclass (with negative ids) but with final fields, and at compile time we would reference the right R field in the generated code. This would mean we wouldn't need to do any change to@EActivity, and when referencing library project ids you would do@EActivity(R_.layout.someLayout).Any opinion on that ?
The RoboGuice guys decided on (tag="main") for R.id.main. I'm not a big fan on using strings, because it breaks refactoring (e.g. you don't get a compilation error if you remove the id or if you misspell it). I'd prefer the R_ approach personally.
Ok :) . One note though regarding strings : refactorings would not be a problems for us, because we can check the string at compile time and verify that the id exist. This is in fact what we do when you don't put any id and use the method name in
@ViewById.Ok the next step here will be to implement a mechanism that generates the R_ class based on the R class, with all inner classes copied, final fields and negative ids. Then it would just be a matter of tweaking the mechanism that checks id to take negative values into account.
Just a quick update. In case you want to use Library Project before we implement support for it in AndroidAnnotations, there are ways to go around it, and still benefit from AA in the interesting parts.
Quoting myself from https://groups.google.com/d/msg/androidannotations/E8NBj08JrqU/jJCjBBCdgmoJ
- View injection and event binding can be done through "convention naming" instead of specifying the R id in the annotation (eg, if you have a "my_view" id, name your annotated field "myView" or your annotated method "myViewClicked").
- Specifying the layout will have to be done in the good old way, using setContentView in onCreate. View injection and other good stuff still work even if you inject the layout manually.
- added a commit that references this issue
on Jun 21, 2012
I have an application that uses aa, but since I have decided to also provide the app in a free version I wanted to move the main app into a library project (The free version is a small project that just injects ads in the activities). When I initially turned the main project into a library (check isLibrary in Project->Properties->Android) it was fine, but as soon as I made a change to the main projects code it gives me tons of errors as seen below. The only way to fix the errors is to convert the main project back to a non-library project, force a compile, and then turn it back to a library project, easy to do but a waste of time.