Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Proguard keeps Activity class in Android?

I have applied ProGuard to my Android application.

I'm using

android-studio/sdk/tools/proguard/proguard-android.txt

as a configuration file, changing nothing.

In this file I can see the only statement regarding Activity:

We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

It follows from that the Activities class names are obfusctated by ProGuard while some methods are preserved as they are. This is understandable.

However, in my application I then create an Activity Class from a string using

Class.forName("my.app.MyActivity")

then I start this Activity and it starts fine.

But that means Activity-derived classes are not obfuscated??. It should have failed because ProGuard does not have -keep class directive for Activity, it only has -keepclassmembers.

Can someone, please, explain, if I can rely on the behaviour I observe? Or do I misunderstand the -keepclassmembers directive?

like image 805
Alexander Kulyakhtin Avatar asked Dec 16 '13 20:12

Alexander Kulyakhtin


2 Answers

From the ProGuard FAQ:

Does ProGuard handle Class.forName calls?

Yes. ProGuard automatically handles constructs like Class.forName("SomeClass") and SomeClass.class. The referenced classes are preserved in the shrinking phase, and the string arguments are properly replaced in the obfuscation phase. With variable string arguments, it's generally not possible to determine their possible values. They might be read from a configuration file, for instance. However, ProGuard will note a number of constructs like "(SomeClass)Class.forName(variable).newInstance()". These might be an indication that the class or interface SomeClass and/or its implementations may need to be preserved. The developer can adapt his configuration accordingly.

So, ProGuard's being cleverer than you expected: it will automatically detect and handle simple cases of the use for forName(). Even if the class isn't referenced in the Android manifest file, ProGuard will obfuscate the class name in both the class and in your call to forName().

For Activities, it wouldn't surprise me if you're doubly-covered by both this behaviour and by the Android-specific input to ProGuard that's part of the build process, as @laalto mentions in his answer.

like image 96
Matt Gibson Avatar answered Oct 15 '22 11:10

Matt Gibson


Because the activities are listed in the manifest and classes referenced there are automagically kept. This is needed because the Android framework accesses these app entry points via reflection.

From here:

The build process runs the tool aapt to automatically create the configuration file bin/proguard.txt, based on AndroidManifest.xml and other xml files. The build process then passes the configuration file to ProGuard. So ProGuard itself indeed doesn't consider AndroidManifest.xml, but aapt+ProGuard do.

like image 34
laalto Avatar answered Oct 15 '22 11:10

laalto