13

I have a issue that Proguard is not working when you declare a anonymous class within a anonymous class. This is what it looks like in a basic example:

public class Class1 {
  public void function1 (){
     new Class2(){
        @Override
        public void function2(){
          new Class3(){
            @Override
            public void function3(){
              // do something
            }
          }
        }
     }
  }
}

During a gradle build script proguard is being executed. Now i get the following error:

 my.package.Class1$2$1: can't find enclosing method 'void function2()' in program class my.package.Class1$2

If I change the code to just have 1 "level" of anonymous classes proguard is finishing without errors. This works:

public class Class1 {
  public void function1 (){
      Class3 class3Instance = new Class3(){
            @Override
            public void function3(){
              // do something
            }
      }
      new Class2(){
        @Override
        public void function2(){
           //do something with class3Instance  
        }
     }
  }
}

The project is a android project, though as far as I know that should not matter.

I tried all different kind of -keep rules for Class1, but nothing worked. Is this not supported by Proguard or do I have to add a rule to get it to work?

UPDATE 1:

As requested the structure if the interface used for the anonymous classes. The interface for Class2 is defined as follows:

public class Class2IntefaceEnclosingClass {
    public interface Class2 {
        void function2();
    }
}

The interface for Class3 is slightly different:

public interface Class3IntefaceEnclosingInterface {
    interface Class3 {
        void function3();
    }
}

Note: I can not change the layout of the interfaces since they are provided by android.

Arne Fischer
  • 922
  • 6
  • 27
  • 1
    Class2 must be extending some class (say Foo). You can have keep clause some thing like this. -keep class * extends Foo {public void function2;} – user3161880 Sep 27 '16 at 10:00
  • Class2 implements a interface. Which is in turn defined as a inner interface of a interface (It is from Android). I tried: `-keep class * extends package.OuterInterface { *; }` and `-keep class * extends package.OuterInterface.InnerInterface { *; }` and `-keep class * extends package.OuterInterface$InnerInterface { *; }`. I also activated `-keepattributes InnerClasses`. No luck unfortunately. – Arne Fischer Sep 27 '16 at 11:11
  • 1
    Could you please share the exact structure of the interface and its usage, to understand the nesting. (Exact fully qualified names are not expected) – user3161880 Sep 28 '16 at 07:00
  • I updated my original post with the requested information. – Arne Fischer Sep 28 '16 at 13:25
  • Please try adding below keep options. `-keep interface your.package.Class2IntefaceEnclosingClass$Class2 {*;}` and `-keep interface your.package.Class3IntefaceEnclosingInterface$Class3 { *;}`. Let me know if it works. – user3161880 Sep 29 '16 at 06:14
  • Still the same behaviour. – Arne Fischer Sep 29 '16 at 07:38

1 Answers1

1

You can try to use @Keep annotation above function1(), function2() and function3().

public class Class1 {
  @Keep
  public void function1 (){
     new Class2(){
        @Keep
        @Override
        public void function2(){
          new Class3(){
            @Keep
            @Override
            public void function3(){
              // do something
            }
          }
        }
     }
  }
}