Stripping unused Java code (from components)

MartRoosmaaMartRoosmaa Mart RoosmaaEEMember, Beta

I'm trying to minimise the APK size. And I'm suspecting bulk of the compiled classes.dex is actually the code from the support libraries which isn't being used. And I want it gone :)

Anyone know of an elegant way to inject Proguard into the build process? Maybe even how to get a list of java classes used in C# world to pass into Proguard? Though I'm willing to manually maintain the configuration of what to keep and what to strip.

I'm thinking the best bet would be to hack the build system a bit to get Proguard into the process. No idea it will work or not.

Posts

  • MartRoosmaaMartRoosmaa Mart Roosmaa EEMember, Beta

    Ok, managed to add proguard to the build process. After stripping out all of the unused code the classes.dex went from 2.8M -> 0.7M.

    Next up: a Cecil tool to inspect the IL for used Java classes and generate the proguard configuration file automatically.

  • MartRoosmaaMartRoosmaa Mart Roosmaa EEMember, Beta

    If anyone else is interested in this, then check out XamGuard on Github.

  • TomOpgenorthTomOpgenorth Tom Opgenorth CAXamarin Team Xamurai

    Cool stuff! Thanks.

  • jaynanavatijaynanavati jay nanavati USMember

    Hi MartRoosma, How you managed to make it work? Can you share your working sample ?

    I am trying the same i.e. XamGuard but getting this error:

    The specified task executable location "C:\Users[userid]\AppData\Local\Android\android-sdk\tools\proguard\bin\proguard.sh" is invalid.

    Thanks.

  • MartRoosmaaMartRoosmaa Mart Roosmaa EEMember, Beta

    I'm a OSX users, so XamGuard is completely untested on Windows. I did make some assumptions and was hoping it would work, but guess that didn't turn out so well.

    In your case it seems that the platform check in OS.cs is failing.

    I'd also like to take the chance of verifying my assumption I made about Windows. Does the C:\Users\[userid]\AppData\Local\Android\android-sdk\tools\proguard\bin\proguard.bat file exist?

    Regarding the platform check any suggestions (and/or pull requests) are welcome. As I don't have a Windows machine myself, it is very difficult for me to fix with any certainty :)

  • jaynanavatijaynanavati jay nanavati USMember

    Thanks for the prompt response. Yes the file proguard.bat exist. But it seems that build process is looking for proguard.sh but that file is not present there.

  • MartRoosmaaMartRoosmaa Mart Roosmaa EEMember, Beta

    Ok, changed the platform detection logic a bit. Can you test against the master branch (compiling from source)? If it works, I'll push it to NuGet.

  • jaykamaleshjaykamalesh jay kamalesh USMember

    Thanks. It did work at some extent. It was looking for proguard.jar file along side the packages folder in solution. It was not there. So I copied lib folder there and it worked. Then it gave following error:

    Error 1 Expecting class path separator ';' before '\Reference' in argument number 6 C:\Users\Documents\Visual Studio 2012\Projects\AndroidApplication2\AndroidApplication2\PROGUARD AndroidApplication2

  • MartRoosmaaMartRoosmaa Mart Roosmaa EEMember, Beta

    It not being able to find proguard.jar is strange, proguard.bat should take care of detecting the correct location of proguard.jar.

    Regarding the 2nd issue, it might the case of spaces in the path name. Can you try to move your solution to some directory which doesn't have spaces in its path?

  • jaynanavatijaynanavati jay nanavati USMember

    Thanks for actively looking into it. I tried and moved the solution to a directory which does not contain space but it still gave the same error. Also one quick question, how much setup it takes to run this on Mac?

  • MartRoosmaaMartRoosmaa Mart Roosmaa EEMember, Beta

    If you've already got Xamarin stuff set up, and monodevelop-nuget-addin installed, then it should be just a matter of adding the NuGet package and editing the .csproj file.

    In the build log you probably have something like this:

        Target _RunProguard:
            Tool /Users/mart/Android/SDK/tools/proguard/bin/proguard.sh execution started with arguments: -injars obj/Release/android/bin/classes -libraryjars /Users/mart/Android/SDK/platforms/android-19/android.jar -libraryjars /Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v4.4/mono.android.jar -outjar obj/Release/android/proguard -include /var/folders/2j/36dgft7j2xl_898mq8h5lgg80000gn/T/tmp7933dbad.tmp -include Proguard.cfg 
    

    I'm interested in the Tool line where it shows the path & arguments for proguard.bat. Maybe it'll give a hint what's going on.

  • jaynanavatijaynanavati jay nanavati USMember

    hmm.. Since I was writing one article on Xamarin Android build obfuscation and optimization and I was too finding a way to incorporate proGuard in build process and I came across your project. I will definately help you out on making this work on Visual Studio in Windows. Right now I was just trying to compare obfuscated and not obfuscated classes.dex files. Let me see how I will set it up in my old Mac.

    Also, I did not see any build output log generated in my Visual Studio 2012. I looked in all directory inside solution. Does it get created somewhere else? Where it gets created in your case?

  • MartRoosmaaMartRoosmaa Mart Roosmaa EEMember, Beta

    Awesome!

    I see the build (and proguard) output in [Xamarin Studio] the Errors->Build output panel.

    Though most of the distributed libraries (when in .jar form) are already obfuscated, so unless its your own Java project there is usually no need to obfuscate again (especially since it might break some of the C# bindings), thus the primary motivation behind this is to strip out unused Java code.

  • jaynanavatijaynanavati jay nanavati USMember

    Interesting. When I decompiled classes.dex to jar file using dex2jar from xamarin generated apk file, I was able to see the java code without any obfuscation. So I thought to plug ProGuard for obfuscation.

  • MartRoosmaaMartRoosmaa Mart Roosmaa EEMember, Beta

    If you obfuscate the public API then Xamarin will not be able to function as the communication between C# to Java happens via JNI, which requires the knowledge of the class/member names on the Java side (hardcoded strings). Sometimes it also uses private already obfuscated stuff, so even reobfuscating private stuff might break stuff as well.

    Taking it a step further and actually updating the C# side with the obfuscated things. Well, it's possible, but hard. And in my opinion totally not worth the effort.

    No code is that valuable. And if it is, and it's Java, you can obfuscate the private parts before binding it as an Android library project.

  • jaynanavatijaynanavati jay nanavati USMember

    Thanks Mart. This clears up a lot. :)

  • GuyonRocheGuyonRoche Guyon Roche NOMember

    Just wondering - is there any way to use XamGuard (or something like it) in the Xamarin Studio? I can't afford the Visual Studio option...

  • MartRoosmaaMartRoosmaa Mart Roosmaa EEMember, Beta

    Nuget (and XamGuard) works fine on Xamarin Studio - just need the Nuget addin. (Xamarin Studio 5, in beta currently, has Nuget support built in.)

    But as mentioned previously it might not work on windows out of the box sadly :( it should work fine on OSX though.

  • sarahzohar88sarahzohar88 sarah zohar USMember

    Yes i check it

  • HuiZhangHuiZhang Hui Zhang USMember

    Have anyone successfully use XamGuard, and how effectively will it reduce the size of apk? I am struggling to reduce my app size down from 16M.

  • StevaSteva Stevan Mladenovic RSMember ✭✭✭

    I tried it on windows and it gives me this error:
    Unable to access jarfile ..\lib\proguard.jar

    File is there so have no idea what to do to resolve this error. Any ideas?

  • alinjojobaalinjojoba alin jojoba INMember ✭✭

    I have run it successfully!
    But it doesnt reduce the size of apk.i doubt about :is it possible to reduce the size or not?

    if any of you wanna help for running just ask for help!

  • RichardUrwinRichardUrwin Richard Urwin GBMember

    When i run it (in VS2013), it seems to ignore all of the keep statements.

    For example, I have this line in Proguard.cfg:

    -keep class android.support.** { *; }

    yet I'm still getting this error:

    17>PROGUARD : warning : android.support.v4.app.Fragment: can't find referenced class android.support.annotation.Nullable

    I've tried various keep statements, such as:

    -keep class android.support.v4.app.* { *; }

    but nothing works.

    Can you help?

    Thanks,
    Rich

  • alinjojobaalinjojoba alin jojoba INMember ✭✭

    Hi,
    Have anyone success to reduce the apk ?

  • KenYeeKenYee Ken Yee USMember

    I get this error when trying to run it :-(
    task does not have the property compiledjavadirectory defined

  • CheesebaronCheesebaron Tomasz Cielecki DKInsider, University mod

    This is built into newer versions of Xamarin.Android and if you look at the GitHub issues you might find that the author is working on other projects now.

    So use the built in stuff.

  • AjaySharma.5121AjaySharma.5121 Ajay Sharma USMember

    @MartRoosmaa : I think XamGuard is not available on github now. Please look https://www.nuget.org/packages/XamGuard

Sign In or Register to comment.