"Abstract class instantiation," you say. "Impossible!"
Here's my code:
public static AbstractFoo getAbstractFoo(Context context) {
try {
Class<?> klass = Class
.forName("com.bat.baz.FooBar");
Constructor<?> constructor = klass.getDeclaredConstructor(
String.class, String.class);
constructor.setAccessible(true);
AbstractFoo foo = (AbstractFoo) constructor.newInstance(
"1", "2");
return foo;
} catch (ClassNotFoundException e) {
// Ignore
} catch (NoSuchMethodException e) {
throw new InflateException(
"No matching constructor");
} catch (IllegalAccessException e) {
throw new InflateException("Could not create foo", e);
} catch (InvocationTargetException e) {
throw new InflateException("Could not create foo", e);
} catch (InstantiationException e) {
throw new InflateException("Could not create foo", e);
}
return null;
}
com.bat.baz.FooBar is a private class that extends AbstractFoo. Without Proguard, this code runs on my Android device. With it, it fails on the NoSuchMethodException try/catch.
I continue to add statements to my Proguard config file like
-keep public abstract class AbstractFoo
{public *;protected *; private *;}
But that doesn't solve the problem. How can I get Proguard to accept that this is a valid way to instantiate the AbstractFoo object? At least, if it works without Proguard, it should work with it.
ProGuard is removing the constructor from the code, because it appears unused. ProGuard can't detect that the constructor is being called by reflection. So, you have to keep it explicitly:
-keepclassmembers class com.bat.baz.FooBar {
<init>(java.lang.String, java.lang.String);
}
Please note that you may have better chances with questions like these on ProGuard's help forum.