Menu
Who Do Is
  • Home
  • What
  • How
  • Is
  • Can
  • Are
  • Does
  • Do
  • Why
  • Who
  • Where
  • Which
  • Which
  • Should
  • Will
  • When
  • What’s
  • Did
Who Do Is

[ANSWERED] java – Android Enum: generate AAR binary with R8 on and throws “Function invocation ‘name()'” exception in client app

Posted on November 14, 2022

Solution 1 :

The Kotlin compiler uses Kotlin metadata in the class files to determine what is a Kotlin property. Therefore, if the Kotlin metadata is not maintained, the Kotlin compiler will not be able to tell that name is a property and it will see it as Java code and will therefore insist that you call the name() method.

R8 has added support for maintaining and rewriting Kotlin metadata in AGP 4.1 beta3. Therefore, if you update to that version and put the following in your library shrinker configuration file, hopefully, that should solve your issue.

# Keep kotlin.Metadata annotations to maintain metadata on kept items.
-keepattributes RuntimeVisibleAnnotations
-keep class kotlin.Metadata { *; }

Problem :

This is a pretty rare case and I have tried googled around but unfortunately nothing came out.

Basically I wanted to create a library module and build an aar binary from it to share by different client apps. But one strange thing happens when I created an enum class in the library module:

When R8 minifyEnabled is off the generated aar file can be imported to client app and compiles properly. But when minifyEnabled is on, it starts to throw this error for calling the enum “.name” property:

Function invocation 'name()' expected

More details below:

In library module

ScaleTyp.kt:

enum class ScaleType constructor(private val text: String) {
    LARGE("large"),
    SMALL("small");
    override fun toString(): String {
        return text
    }
}

build.gradle:

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles "consumer-rules.pro"
    }

    buildTypes {
        debug {
            testCoverageEnabled = false
            minifyEnabled true
            proguardFiles 'proguard-rules.pro'

        }

        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}
...

In app module:

place generated aar in libs folder

MainActivity.kt, this is where it throws the error when .name is called, which should be completely legal in kotlin.

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.mylibrary.ScaleType

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        ScaleType.LARGE.name //compile failed
    }
}

build.gradle in app module

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "com.example.myapplication"
        minSdkVersion 19
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        debug {
            testCoverageEnabled = false
            minifyEnabled false
            shrinkResources false
            proguardFiles 'proguard-rules.pro'

        }

        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    ...
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.0'
    implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'], exclude: [])
    ...
}

After digging into the AAR binary, I have observed that when minifyEnabled is off in lib module the ScaleType class is translated to

public final enum class ScaleType private constructor(text: kotlin.String) : kotlin.Enum<com.example.mylibrary.ScaleType> {

therefore in client app this is absolutely fine because this is just the kotlin way of calling name.

ScaleType.LARGE.name //compile pass

but when minifyEnabled is true, it got translated to

public final enum com/example/mylibrary/ScaleType extends java/lang/Enum

then in client app, because it sees ScaleType as a java enum, it will expect developers to call

ScaleType.LARGE.name()
instead of 
ScaleType.LARGE.name // compile failed

I can also confirm that importing library module as source does not have this issue because the compiler has translated all kotlin classes uniformly to java class. They are consistent in this way so it doesn’t have this kotlin to java conflict.

READ  [ANSWERED] android - Problem executing command "flutter build appbundle"
Powered by Inline Related Posts

This is causing big trouble now. For app that imports library module directly, it is fine to call “.name”. But for apps that use aar binary, they have to call “.name()”, and even more painful you still have to use “.name” when debugging the lib module.

Any help would be appreciated.

If you want to try it, you can find sample code here

Recent Posts

  • How can I play with my cat without toys?
  • What is a bag pipe band called?
  • Are Honda Civics actually fast?
  • Are Yankee candles toxic?
  • How do I pair my Michael Kors smartwatch with my Android?

Recent Comments

No comments to show.

Archives

  • January 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022

Categories

  • ¿Cómo
  • ¿Cuál
  • ¿Cuántas
  • ¿Cuánto
  • ¿Que
  • ¿Quién
  • 90” and 108” so you may have to round up to the nearest size.
  • and delete any Spotify folders from it. Once this is done
  • Android
  • Are
  • At
  • Bei
  • blink
  • C'est
  • Can
  • carbs
  • Comment
  • Did
  • Do
  • Does
  • During
  • For
  • Has
  • How
  • In
  • Is
  • Ist
  • Kann
  • Können
  • nouveau
  • On
  • or 108 inches.2020-08-03
  • Où
  • owning
  • Pourquoi
  • Puis-je
  • Quand
  • Quante
  • Quel
  • Quelle
  • Quelles
  • Quels
  • Qui
  • Should
  • Sind
  • Sollte
  • spiritual
  • tap the downward-facing arrow on the top left. A downward-facing arrow will appear underneath each song in the album; they'll turn green as the download completes.2020-07-28
  • Uncategorized
  • Wann
  • Warum
  • Was
  • Welche
  • Welcher
  • Welches
  • Welke
  • Wer
  • Were
  • What
  • What's
  • When
  • Where
  • Which
  • Who
  • Whose
  • Why
  • Wie
  • Will
  • Wo
  • Woher
  • you will receive two curtains each with the same measurements of width 66"" (168cm) x drop 54""(137cm).
  • you'll see a green downward-facing arrow next to each song.2021-02-26
©2023 Who Do Is | Powered by SuperbThemes & WordPress