I originally tried to get help for this problem on StackOverflow but didn't get anything.
http://stackoverflow.com/questions/22418691/why-does-proguard-keepclassmembers-behave-differently-based-on-class-specifier
It seems like it may be a bug...
I've been debugging a ProGuard issue in an Android app I'm writing caused by it removing field names that are needed to extract the fields from a JSON string. To make sure those members remained with their original names, I added this:
-keepclassmembers class com.example.common.regions.** {
!static !final !transient <fields>;
}
This seemed to work and the output mapping.txt showed the following:
com.example.common.regions.RegionMapMeta -> com.example.b.d.b:
java.lang.String mapVid -> mapVid
int mapVersion -> mapVersion
double topLeftLat -> topLeftLat
double topLeftLong -> topLeftLong
double topRightLat -> topRightLat
double topRightLong -> topRightLong
double bottomLeftLat -> bottomLeftLat
double bottomLeftLong -> bottomLeftLong
double bottomRightLat -> bottomRightLat
double bottomRightLong -> bottomRightLong
double boundingTopLat -> boundingTopLat
double boundingBottomLat -> boundingBottomLat
double boundingLeftLong -> boundingLeftLong
double boundingRightLong -> boundingRightLong
int minZoom -> minZoom
int maxZoom -> maxZoom
int maxZoomMinX -> maxZoomMinX
int maxZoomMaxX -> maxZoomMaxX
int maxZoomMinY -> maxZoomMinY
int maxZoomMaxY -> maxZoomMaxY
int stackOrder -> stackOrder
java.lang.String thumbnailImage -> thumbnailImage
java.util.Set mapLayers -> mapLayers
Then I thought I didn't like having to specify directories in ProGuard and that it would be better to have an annotation to distinguish these classes.
@Target(ElementType.TYPE)
public @interface ProguardKeepClassMembers {
}
I then annotated my classes (not the members, just the classes) with @ProguardKeepClassMembers and changed the ProGuard rule to be as such:
-keepclassmembers @com.example.common.ProguardKeepClassMembers class * {
!static !final !transient <fields>;
}
However, this does not work the same. The mapping.txt file has the same fields but now they're being obfuscated.
com.example.common.regions.RegionMapMeta -> com.example.b.d.b:
java.lang.String mapVid -> a
int mapVersion -> b
double topLeftLat -> c
double topLeftLong -> d
double topRightLat -> e
double topRightLong -> f
double bottomLeftLat -> g
double bottomLeftLong -> h
double bottomRightLat -> i
double bottomRightLong -> j
double boundingTopLat -> k
double boundingBottomLat -> l
double boundingLeftLong -> m
double boundingRightLong -> n
int minZoom -> o
int maxZoom -> p
int maxZoomMinX -> q
int maxZoomMaxX -> r
int maxZoomMinY -> s
int maxZoomMaxY -> t
int stackOrder -> u
java.lang.String thumbnailImage -> v
java.util.Set mapLayers -> w
So... Why is -keepclassmembers behaving different when only the class matcher has changed?
ProGuard is probably removing the annotation itself, since the code is not using it. You should keep it:
Alternatively, you can collect such annotations in a jar annotations.jar and specify it as a library (without leaving it in the source code or in libs):
The annotation classes then won't be in the resulting code, which is fine. This is the approach from the example examples/annotations/examples.pro (e.g. in android-sdk/tools/proguard).
Also see the ProGuard manual > Troubleshooting > Unexpected observations after processing > Classes or class members not being kept.