More Related Content Similar to Annotation processing in android (20) Annotation processing in android3. Library use Annotation
Processor
• AndroidAnnotation
• http://androidannotations.org/
• ButterKnife
• https://github.com/JakeWharton/butterknife
• Dagger
• http://square.github.io/dagger/
4. Library (not) use Annotation
Processor
• Retrofit
• http://square.github.io/retrofit/
• galette
• https://github.com/uPhyca/GAlette
11. Dependency - top level
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
}
13. Dependency - app
apply plugin: 'com.android.application'
apply plugin: 'android-apt'
...
...
dependencies {
...
apt project(':annotationprocessor')
compile project(':annotation')
}
16. processor - basic setting
// Supported Annotation
@SupportedAnnotationTypes({"me.lunacat.annotations.MethodAnnotation"})
public class AnnotationProcessor extends AbstractProcessor {
private Filer filer;
private Messager messager;
@Override
public synchronized void init(ProcessingEnvironment env){
super.init(env);
filer = processingEnv.getFiler(); // File instance
messager = processingEnv.getMessager(); // Logger
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
// processing function
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
roundEnv) {}
}
17. processor- gather annotations
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
ArrayList<MethodAnnotation> methodAnnotations = new ArrayList<>();
for (Element e : roundEnv.getElementsAnnotatedWith(MethodAnnotation.class))
{
MethodAnnotation annot = e.getAnnotation(MethodAnnotation.class);
methodAnnotations.add(annot);
}
generateJavaFile(methodAnnotations);
}
18. processor - generate code
private void generateJavaFile(ArrayList<MethodAnnotation> methodAnnotations) throws
IOException {
// create ExtraClass with annotation content
JavaFileObject source = filer.createSourceFile(“in.test.AnnotationGenClass”);
Writer writer = source.openWriter();
try {
PrintWriter pw = new PrintWriter(writer);
pw.println("package in.test;");
pw.println("public class AnnotationGenClass {");
for(MethodAnnotation annot: methodAnnotations) {
pw.println("public static final void " + annot.parameterName() + "() {}");
}
pw.println("}");
pw.flush();
pw.close();
}
finally {
writer.close();
}
}
19. processor - generate resources
private void generateJavaFile(ArrayList<MethodAnnotation> methodAnnotations) throws
IOException {
// create method.txt with annotation contents
FileObject file = filer.createResource(
StandardLocation.SOURCE_OUTPUT,
"",
"methods.txt",
null);
writer = file.openWriter();
try {
PrintWriter pw = new PrintWriter(writer);
for(MethodAnnotation annot: methodAnnotations) {
pw.println(annot.parameterName());
}
pw.flush();
pw.close();
}
finally {
writer.close();
}
}
20. processor - create meta-data
create file: javax.annotation.processing.Processor
file content: me.lunacat.AnnotationProcessor
22. Generate Code - filer
private void generateJavaFile(ArrayList<MethodAnnotation> methodAnnotations) throws
IOException {
// create ExtraClass with annotation content
JavaFileObject source = filer.createSourceFile(“in.test.AnnotationGenClass”);
Writer writer = source.openWriter();
try {
PrintWriter pw = new PrintWriter(writer);
pw.println("package in.test;");
pw.println("public class AnnotationGenClass{");
for(MethodAnnotation annot: methodAnnotations) {
pw.println("public static final void " + annot.parameterName() + "() {}");
}
pw.println("}");
pw.flush();
pw.close();
}
finally {
writer.close();
}
}
23. Generate Code - JavaPoet
for(MethodAnnotation annot: methodAnnotations) {
MethodSpec dumpMethod = MethodSpec
.methodBuilder(annot.parameterName())
.addModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.PUBLIC)
.returns(void.class)
.build();
dumpMethods.add(dumpMethod);
}
// create class
TypeSpec.Builder classBuilder = TypeSpec
.classBuilder("AnnotationGenClass")
.addModifiers(Modifier.PUBLIC);
if ( dumpMethods != null ) {
classBuilder.addMethods(dumpMethods);
}
JavaFile.builder("me.lunacat.annotationgent", classBuilder.build())
.build()
.writeTo(filer);
with dependencies
dependencies {
compile 'com.squareup:javapoet:1.1.0'
}
24. MetaData - bare hand
create file: java.annotation.processing.Processor
file content: me.lunacat.AnnotationProcessor
25. MetaData - Auto
• Auto
• https://github.com/google/auto
@AutoService(Processor.class)
public class AnnotationProcessor extends AbstractProcessor {
}
With dependency:
dependencies {
compile 'com.google.auto.service:auto-service:1.0-rc2'
}
26. Testing
JavaFileObject sampleActivity = JavaFileObjects
.forSourceString("SampleActivity", "package com.example;"
+ "import me.lunacat.annotations.TypeAnnotation; "
+ "@Type("airbnb://example.com/deepLink") public class SampleActivity {}”);
// sampleActivity with AnnotationProcessor with generate source like
assert_().about(javaSource())
.that(sampleActivity)
.processedWith(new AnnotationProcessor())
.compilesWithoutError()
.and()
.generatesSources(
JavaFileObjects.forResource("AnnotationGenClass.java"),
JavaFileObjects.forSourceString("AnnotationGenClass",
"package.."));
with dependencies
dependencies {
testCompile 'com.google.testing.compile:compile-testing:0.6'
}
30. Pass Parameter to Processor
apt {
arguments{
host "http://www.123456789.host/"
}
}
build.gradle (app)
Processor
public synchronized void init(ProcessingEnvironment env) {
String host = env.getOptions().get("host");
}
31. References
• Annotation 101
• http://brianattwell.com/android-annotation-processing-
pojo-string-generator/
• http://hannesdorfmann.com/annotation-processing/
annotationprocessing101/#processing-rounds
• Debug Annotation Processor
• https://turbomanage.wordpress.com/2014/06/09/
debug-an-annotation-processor-with-intellij-and-gradle/