Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin, Proguard and lambdas

I have a neat function that does something on a view:

fun<T : View> Activity.withView(nr : Int, fn : T.()->Unit) {
    (findViewById(nr) as T?)?.fn()
}

Now, when I use this function in my activity:

    withView<Spinner>(R.id.spinner_toolbar) {
        adapter = AdapterIndeksuDlaSpinnera(this@NewMainActivity, PlaylistIndex)

...everything is OK until I use ProGuard. I can see AdapterIndeksuDlaSpinnera gets mangled, as expected, but the application fails when proguarded with "Can't load class AdapterIndeksuDlaSpinnera" (while it should complain about mangled adapter name).

I was able to create temporaty workaround by disabling mangling of all adapters that can be used inside my withView

-keep class pl.qus.xenoamp.adapter.** { *; }

but I don't feel it's a good solution (and I have no idea what other classes can fail this way!). So can anyone explain what is the problem and what ProGuard line should I add to potentially fix similar occurences of other classes used inside withView?

like image 357
ssuukk Avatar asked Feb 19 '16 11:02

ssuukk


Video Answer


1 Answers

This is a tough one. In nutshell, Proguard does not know about Kotlin. It is using a simple code analysis to detect things like Class.forName() and work around them, but may fail for anything more complex. You need to look at generated .class files from build subdirectories (can you post relevant ones?) to find out what really happens.

For now you can do two things:

  • Ask Kotlin devs to add proper obfuscation/optimization support to the Kotlin compiler: this is really the right way to do things, as demonstrated by every non-java compiler in existence;
  • Exclude your own sources from obfuscation (most Activities and Views aren't going to be well-obfuscated anyway).
like image 141
user1643723 Avatar answered Oct 08 '22 19:10

user1643723