Reputation: 1811
I'm working on a library that generates a class file based on annotated classes and fields at compile time (when hitting build). So far everything is fine (class can be generated). However, I have a problem in how to find such a generated class when the application is launched (the class needs to be accessed within the onCreate
method of the Application
).
The code looks something like this:
- Application class of an Android app -
@Override
public void onCreate() {
super.onCreate();
MyLib.setup(this);
}
And within the class MyLib
, something like this needs to be done:
public void setup(Application app) {
String className = String.format("%s.%s", "packageName", "generatedClassName");
Class<?> myGeneratedClass = Class.forName(className);
...
}
The problem is I don't know how to find the class without knowing its package name and also don't know how to find its package name.
I could think of a way to do this is passing the package name into one of the annotation like @MyAnnotation("package_name") to use it when generating the class at compile time and obtaining that class at runtime.
However I'm just wondering if there is any other cleaner ways to achieve this. Is there any way to either:
1. Obtain the Application package name during annotation processing
2. Look for a class at runtime without knowing its package (only know the Application package). I did try Package.getPackages()
within MyLib.setup()
. However this returns an empty array.
Upvotes: 3
Views: 1357
Reputation: 4222
This is a well-researched issue. The simplest approach is having your users annotate the application package (yes, annotating a package is possible) or pass the name of app package via javac parameter (android-apt and new versions of Android Gradle plugin have native support for those). This is cheap and will get you going quickly.
Getting package name heuristically is possible and AndroidAnnotations has a chunk of code for that (more precisely, for finding AndroidManifest.xml and locating R.java), both of which can give out app package. Beware, those methods are not pretty. Note, that AndroidAnnotations have plugin system, so you can get access to that functionality without re-doing their work by writing a plugin and declaring dependency on their main processor.
Finally, you can write your own Gradle plugin and access this kind of information directly.
Upvotes: 4
Reputation: 1736
Override Application class
private static Context sContext;
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
sContext = base;
}
public static Context getAppContext() {
return sContext;
}
To get package name
YourApplication.getAppContext().getPackageName();
Edited:
To get package name of annotated element in class extended from AbstractProcessor
you can use this
final String originalPackageName = element.getEnclosingElement().toString();
where element is TypeElement instance
Upvotes: 1