Search code examples
androidandroid-gradle-pluginproguardandroid-r8

XML resource names are changed in release builds after upgrading Gradle plugin


After upgrading the Gradle plugin to 4.2.0 (before that, I didn't have this problem), it seems the names of XML resource files are changed when building a release build, for instance from res/xml/settings_master_switch_1.xml to res/cb1.xml.

This presents a problem with a library I wrote, since it takes the name of a resource given in xml, for instance

<com.smp.masterswitchpreference.MasterSwitchPreference
       ..
        app:ms_includedPrefScreen="@xml/settings_master_switch_1" />

and looks up the resource id with this function

fun resInt(resName: String?, type: String): Int? {
                resName ?: return null
                val f = File(resName).nameWithoutExtension
                return context.resources.getIdentifier(f, type, context.packageName)
            }

The consumer of this library can simply have

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

or even with minifyEnabled false to generate the problem.

The library with demo app can be found here https://github.com/svenoaks/MasterSwitchPreference

So I assume I must add some type of R8/Proguard or Gradle setting in consumer of this library to not change the name of the xml resource? What would this rule be?

I've tried both defining the resources to keep in res/raw/keep.xml of the consumer app -

<resources xmlns:tools="http://schemas.android.com/tools"
 tools:keep="@xml/settings_master_switch_1,@xml/settings_master_switch_2,@drawable/ic_baseline_cake_24.xml" />

and this rule in the proguard-rules.pro

-verbose
-keepattributes InnerClasses
-keep class **.R
-keep class **.R$* {
    <fields>;
}

without success, the plugin renames the XML resources anyway.


Solution

  • In my case all I needed to do was change the attr declaration from integer to string:

       <attr name="ms_includedPrefScreen" format="string"/>
            <attr name="ms_excludedPrefScreen" format="string"/>
    

    and remove the "@" annotation from the consumer, so that a literal string with the correct name is passed in:

    app:ms_includedPrefScreen="xml/settings_master_switch_1"