Wouldn't it make sense for B4A to automatically add the kind of keep rule that you suggest here as the manual solution?
In the example, B4A already detects:
Code:
com.google.android.gms.ads.AdLoader.Builder
but it does not know that:
B4X:
builder.RunMethod("build", Null)
returns an
AdLoader.
Your suggested manual solution is therefore:
Code:
-keep class com.google.android.gms.ads.AdLoader { *; }
My first thought would be: could B4A simply generate this additional rule automatically whenever it detects a nested class such as:
So detecting:
Code:
com.google.android.gms.ads.AdLoader.Builder
would automatically also keep:
Code:
com.google.android.gms.ads.AdLoader
This would cover the very common
Builder -> built object pattern without requiring B4A to analyze the return type of
RunMethod.
A slightly more general variant would be to generate a wildcard rule such as:
Code:
-keep class com.google.android.gms.ads.AdLoader* { *; }
This would also protect related nested classes and would probably cover more cases with very little additional compiler logic.
An even more conservative option would be package-wide keep rules:
Code:
-keep class com.google.android.gms.ads.** { *; }
whenever
JavaObject accesses a class from that package.
This would obviously reduce the amount of shrinking and optimization R8 can perform. But I suspect that for most B4A projects compatibility is more important than achieving the maximum possible R8 optimization. Only a minority of projects will probably depend on aggressive shrinking, whereas a runtime
ClassNotFoundException or
MethodNotFoundException caused by
JavaObject is quite difficult to diagnose.
So perhaps a conservative automatic rule could be the safer default, while users who really care about maximum R8 optimization could still use more specific rules manually.