How to write

an annotation processor
in Android
Ivan Kušt
• Generics

http://docs.oracle.com/javase/tutorial/java/generics/

• Reflection

http://docs.oracle.com/javase/tutorial/reflect/

• Annotations

http://docs.oracle.com/javase/1.5.0/docs/guide/apt/
mirror/overview-summary.html
How to write code faster?
Let’s look at our options
Generics Reflection Annotations
Speed Fast Slow
Fast (if using
compile time)
Ease of use Easy Medium Advanced
“Freedom" - generic types
- modify everything
at run-time
- generate code
during compile
• use generics for type agnostic structures when
possible (e.g. lists) - it’s easy and fast

• when that isn’t enough, use annotation processing -
generate code that is boring to write

• generated code isn’t “visible” - use reflection to access
it at run time from the code that you write
Approach
Let’s get our hands dirty
• actually only the keyboard gets dirty over time

• prerequisites:

- Android Studio (tested on version 0.4.0)

- enable annotation processing

(Open preference and navigate to Compiler → Annotation Processors.
Check "Enable annotation processing”)

- apt plugin https://bitbucket.org/hvisser/android-apt

• what is an annotation processor made of?

- definition of annotations using @interface

- a class that extends AbstractProcessor

- entry containing processor name in 

META-INF/services/javax.annotation.processing.Processor
Project structure
• API project 

- annotation definitions

- other non-generated code

• Compiler project

- annotation processor implementation

- annotation definitions (from API project) on
classpath

• Application project 

- android application project

- references to API and Compiler projects
API project
• android library project

• contains annotation definitions, for example:









Compiler project
• standard java library project

- this is required in order to see APT classes

• API project sources must be in classpath (build.gradle): 









Compiler project
• AbstractProcessor implementation

- override process(…) method



- return true if processing was successfull



- add following annotations to processor class:



@SupportedAnnotationTypes(“your.package.AnnotationName”)

@SupportedSourceVersion(SourceVersion.RELEASE_7)

• create file: 

src/main/resources/META-INF/services/javax.annotation.processing.Processor

• add fully qualified class name of your processor class to the
file (e.g. co.infinum.annotations.processor.TestProcessor)

Application project
• referencing API and Compiler projects in build.gradle:
Butterknife library
• UI dependency injection library

• View injection on Activities or
arbitrary objects

- no more writing findViewById(…)

• simplifying view holder pattern

• on click listener injection
View injection
class ExampleActivity extends Activity {	
@InjectView(R.id.title) TextView title;	
@InjectView(R.id.subtitle) TextView subtitle;	
@InjectView(R.id.footer) TextView footer;	
!
@Override public void onCreate(Bundle savedInstanceState) {	
super.onCreate(savedInstanceState);	
setContentView(R.layout.simple_activity);	
ButterKnife.inject(this);	
// TODO Use "injected" views...	
}	
}	
• use @InjectView on fields representing view elements

- fields can’t be private or protected

• call ButterKnife.inject(this) in onCreate()
Resources
• annotations example:

https://github.com/ikust/hello-annotations

• http://turbomanage.wordpress.com/2012/09/28/
annotation-processor-android-eclipse/

• https://bitbucket.org/hvisser/android-apt

• http://www.javacodegeeks.com/2012/11/java-
annotations-tutorial-with-custom-annotation.html

• http://blog.retep.org/2009/02/13/getting-class-
values-from-annotations-in-an-annotationprocessor/

• http://jakewharton.github.io/butterknife/

Infinum Android Talks #02 - How to write an annotation processor in Android

  • 1.
    How to write
 anannotation processor in Android Ivan Kušt
  • 2.
    • Generics
 http://docs.oracle.com/javase/tutorial/java/generics/
 • Reflection
 http://docs.oracle.com/javase/tutorial/reflect/
 •Annotations
 http://docs.oracle.com/javase/1.5.0/docs/guide/apt/ mirror/overview-summary.html How to write code faster?
  • 3.
    Let’s look atour options Generics Reflection Annotations Speed Fast Slow Fast (if using compile time) Ease of use Easy Medium Advanced “Freedom" - generic types - modify everything at run-time - generate code during compile
  • 4.
    • use genericsfor type agnostic structures when possible (e.g. lists) - it’s easy and fast
 • when that isn’t enough, use annotation processing - generate code that is boring to write
 • generated code isn’t “visible” - use reflection to access it at run time from the code that you write Approach
  • 5.
    Let’s get ourhands dirty • actually only the keyboard gets dirty over time
 • prerequisites:
 - Android Studio (tested on version 0.4.0)
 - enable annotation processing
 (Open preference and navigate to Compiler → Annotation Processors. Check "Enable annotation processing”)
 - apt plugin https://bitbucket.org/hvisser/android-apt
 • what is an annotation processor made of?
 - definition of annotations using @interface
 - a class that extends AbstractProcessor
 - entry containing processor name in 
 META-INF/services/javax.annotation.processing.Processor
  • 6.
    Project structure • APIproject 
 - annotation definitions
 - other non-generated code
 • Compiler project
 - annotation processor implementation
 - annotation definitions (from API project) on classpath
 • Application project 
 - android application project
 - references to API and Compiler projects
  • 7.
    API project • androidlibrary project
 • contains annotation definitions, for example:
 
 
 
 

  • 8.
    Compiler project • standardjava library project
 - this is required in order to see APT classes
 • API project sources must be in classpath (build.gradle): 
 
 
 
 

  • 9.
    Compiler project • AbstractProcessorimplementation
 - override process(…) method
 
 - return true if processing was successfull
 
 - add following annotations to processor class:
 
 @SupportedAnnotationTypes(“your.package.AnnotationName”)
 @SupportedSourceVersion(SourceVersion.RELEASE_7)
 • create file: 
 src/main/resources/META-INF/services/javax.annotation.processing.Processor
 • add fully qualified class name of your processor class to the file (e.g. co.infinum.annotations.processor.TestProcessor)

  • 10.
    Application project • referencingAPI and Compiler projects in build.gradle:
  • 11.
    Butterknife library • UIdependency injection library
 • View injection on Activities or arbitrary objects
 - no more writing findViewById(…)
 • simplifying view holder pattern
 • on click listener injection
  • 12.
    View injection class ExampleActivityextends Activity { @InjectView(R.id.title) TextView title; @InjectView(R.id.subtitle) TextView subtitle; @InjectView(R.id.footer) TextView footer; ! @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.simple_activity); ButterKnife.inject(this); // TODO Use "injected" views... } } • use @InjectView on fields representing view elements
 - fields can’t be private or protected
 • call ButterKnife.inject(this) in onCreate()
  • 13.
    Resources • annotations example:
 https://github.com/ikust/hello-annotations
 •http://turbomanage.wordpress.com/2012/09/28/ annotation-processor-android-eclipse/
 • https://bitbucket.org/hvisser/android-apt
 • http://www.javacodegeeks.com/2012/11/java- annotations-tutorial-with-custom-annotation.html
 • http://blog.retep.org/2009/02/13/getting-class- values-from-annotations-in-an-annotationprocessor/
 • http://jakewharton.github.io/butterknife/