Adding ProGuard to Android toolchain

Is it currently possible to use ProGuard in the build chain for an Android app?

I found this post from 4 years ago: https://talk.remobjects.com/t/swift-android-is-proguard-or-other-obfuscation-method-supported/6636/2/:

But within the typical Android build process, ProGuard runs post-compilation and pre- APK creation:

So within EBuild, I would imagine this would need to be the first sub-Task of ElementsPostCompileCooper, or at least before Task AndroidPack is run. Is there any way to tweak the build chain to add custom tasks? If not, I would love to see ProGuard added as a new, optional sub-Task of ElementsPostCompileCooper.

1 Like

Matt,

Correct, yes.

Right now there’s no way to do that, no. But if you can let me know specifics of what needs to be done/rund here (the more concrete the better), I can probably find time to integrate this sometime soon.

Note also that Elements of course has native obfuscation built in, so you might to even need ProGuard…

2 Likes

Thanks Marc, I think I’ve run across this in the docs but had forgotten about it. I want to obfuscate code in release builds, and I need to be able to deobfuscate stack traces generated by release builds. In a perfect world, Elements would provide a ProGuard-format mapping.txt file that I could upload to the Google Play Developer Console to deobfuscate stack traces within the Developer Console. But at the very least, I would need to be able to download stack traces and manually deobfuscate. I assume this is possible since a .fx file can be used to reference non-obfuscated names, but I don’t see anything about deobfuscation in the docs.

Also, where exactly am I supposed to place [assembly:Obfuscate] to obfuscate an entire project? Does it matter where?

We do provide. amazing, if not ProGuard compatible (but I could look in to that as well, of you have references to its format).

The .fx contains the machine-readable mapping for referencing & debugging, and I believe we also generate an optional human-readable ma .txt file.

Anywhere. the [assembly: prefix will make sure the aspect is applied to the entire project. See Aspects.

1 Like

Amazing.

I’ll look into it, because this would be really nice to have within the Android dev ecosystem. It’s a .txt file so it can’t be too proprietary :wink:

Unless I’m misunderstanding Aspects, I believe I found a bug related to this. The project appears to build correctly if I place the [assembly:Obfuscate] aspect in the implementation section of a file, but I get build error "E: unexpected number of compiler output files" if I place it anywhere in the interface section. This is true of a newly created Android project as well.

Hm, can you send me a test case just in case? this should be fine in the interface too.

tests.obfuscate.zip (95.3 KB)

I just realized, I believe the test case I uploaded has the aspect in the implementation section. Moving it to the interface section causes that error on my machine though.

EDIT: Here’s the same project with the aspect in the interface section (fails on my machine)

tests.obfuscate.zip (95.3 KB)

Odd. I think the reverse is actually the case. the aspect seems to be ignored in implementing dentation section (thats a bug), when I move it to interface, it *compiles< but fails with

D:             CompilerOutput for Cooper-Android
D:               - <CompilerOutput: /Users/mh/Library/Application Support/RemObjects Software/EBuild/Obj/tests.obfuscate-793DAC6F94C24AAE788CFCD70B8A0F875B955E8D/Debug/Cooper-Android/tests.obfuscate.fx [Target: Cooper-Android]>
D:               - <CompilerOutput: /Users/mh/Library/Application Support/RemObjects Software/EBuild/Obj/tests.obfuscate-793DAC6F94C24AAE788CFCD70B8A0F875B955E8D/Debug/Cooper-Android/tests.obfuscate.jar [Target: Cooper-Android]>
...
E:                   Unexpected number of compiler output files.

which seems to be an ebuild bug I’ll investigate now. It seems later parts of the Android toolchain do not expect non-.jar files (ie the .fx or the map) being generated by the compiler.

1 Like

Thanks, logged as bugs://82948

EBuild fixed; ignored aspect in implementation logged above.

1 Like

Great. Is the fix for the aspect being ignored or for the compilation not working? Once the compilation is working correctly (if not already) could I get a private build of this when you get a chance? I’m planning to push a release asap and would really like to have this functionality in it.

The Ebuild fix I made is for the build failing later, after the compile did obfuscate. I’ve started a new full produce t build and will send you a new installer once its done in ~1h. You should then be good to go with he aspect in the interface section.

1 Like

Perfect. Thanks!

Up now.

1 Like

bugs://82948 got closed with status fixed.

The build is running and compiling correctly now with assmebly:Obfuscate in the interface section, but the code still does not seem to be obfuscated, at least not looking at the stack traces. I created a new test project where onCreate calls doSomething, which calls doSomethingElse, which intentionally crashes with a null pointer. I ran the same app with debug symbols Off and with them On, and neither stack trace is what I would expect from obfuscated code…

Without Debug Symbols:

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
   at tests.obfuscate.__Global.doSomethingElse (Unknown Source:1)
   at tests.obfuscate.MainActivity.doSomething (Unknown Source:0)
   at tests.obfuscate.MainActivity.onCreate (Unknown Source:9)

With Debug Symbols:

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
	at tests.obfuscate.__Global.doSomethingElse (C:\Users\mattr\Code\Elements\tests.obfuscate\MainActivity.pas:45)
	at tests.obfuscate.MainActivity.doSomething (C:\Users\mattr\Code\Elements\tests.obfuscate\MainActivity.pas:39)
	at tests.obfuscate.MainActivity.onCreate (C:\Users\mattr\Code\Elements\tests.obfuscate\MainActivity.pas:34)

Expected something like:

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
	at a.a.a (a.a.a:1)
	at a.b.a (a.b.a:0)
	at a.b.b (a.b.b:9)