title: Android - Custom annotation TargetFlavor like TargetApi but for flavors
body: <p>I'm currently working to create a custom annotation which does the same work as <code>@TargetApi()</code> but with my flavors.</p>
  
  <h2><strong>The Case</strong></h2>
  
  <p>In my case, I need to use a certain method (in a class called <code>Navigator</code>) to redirect my application to another screen but I create this screen only in one of the flavors. So when I switch to another Build Variant, my Android Studio display an error: <code>Unresolved reference</code>, as expected.</p>
  
  <p>I have 3 flavors: <code>device1</code>, <code>device2</code> and <code>device3</code>. Also <code>device1</code> has this unique screen (called <code>UniqueActivity</code>) and all flavors have access to <code>Navigator</code> class.</p>
  
  <p>I see the use case like this: </p>
  
  <pre><code>@TargetFlavor(currentFlavor = BuildConfig.FLAVOR, targetFlavor = "device1")
  </code></pre>
  
  <h2><strong>The (almost perfect) solution</strong></h2>
  
  <p>So I thought about preprocessor annotation to ignore method when the selected flavor (by the Build Variant) does not correspond to the target flavor. I followed <a href="https://medium.com/@iammert/annotation-processing-dont-repeat-yourself-generate-your-code-8425e60c6657" rel="noreferrer">this article</a>.</p>
  
  <p>And here is what I achieved:</p>
  
  <p><strong>TargetFlavor annotation:</strong></p>
  
  <pre><code>@Retention(RetentionPolicy.SOURCE)
  @Target(ElementType.METHOD)
  public @interface TargetFlavor {
      String currentFlavor();
      String targetFlavor();
  }
  </code></pre>
  
  <p><strong>TargetFlavorProcessor:</strong></p>
  
  <pre><code>public class TargetFlavorProcessor extends AbstractProcessor {
  
      private Filer filer;
      private Messager messager;
      private Elements elements;
      private Map&lt;String, Boolean&gt; methodWithFlavor;
  
      @Override
      public synchronized void init(ProcessingEnvironment processingEnv) {
          super.init(processingEnv);
  
          filer = processingEnv.getFiler();
          messager = processingEnv.getMessager();
          elements = processingEnv.getElementUtils();
          methodWithFlavor = new HashMap&lt;&gt;();
  
      }
  
      @Override
      public boolean process(Set&lt;? extends TypeElement&gt; set, RoundEnvironment roundEnvironment) {
  
          for (Element element : roundEnvironment.getElementsAnnotatedWith(TargetFlavor.class)) {
  
              if (element.getKind() != ElementKind.METHOD) {
                  messager.printMessage(Diagnostic.Kind.ERROR, "Must be applied on methods");
                  return true;
              }
  
              TypeElement typeElement = (TypeElement) element;
              TargetFlavor annotation = element.getAnnotation(TargetFlavor.class);
              methodWithFlavor.put(
                      typeElement.getSimpleName().toString(),
                      annotation.targetFlavor().equals(annotation.currentFlavor()));
          }
  
          for (Map.Entry&lt;String, Boolean&gt; methods : methodWithFlavor.entrySet()) {
  
              if (!methods.getValue()) {
  
                  // Here, I want the compiler to ignore method which not correspond
  
              }
  
          }
  
          return true;
  
      }
  
      @Override
      public Set&lt;String&gt; getSupportedAnnotationTypes() {
          return Collections.singleton(TargetFlavor.class.getCanonicalName());
      }
  
      @Override
      public SourceVersion getSupportedSourceVersion() {return SourceVersion.latest();}
  
  }
  </code></pre>
  
  <p>But I'm stuck when I want to force my compiler to ignore certain methods selected by <code>@TargetFlavor()</code>.</p>
  
  <p>Is there a better way to do this, or am I doing this correctly?</p>