5

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.

Steve M
  • 9,296
  • 11
  • 49
  • 98

3 Answers3

3

Generally one may want to keep class R:

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

But one can also annotate, in order to keep specific resources:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@xml/settings_master_switch_1" />
Martin Zeitler
  • 1
  • 19
  • 155
  • 216
  • I tried both of those in the consumer app, and unfortunately neither of those work with the Gradle plugin 4.2.0, the resources are renamed anyway. – Steve M May 08 '21 at 19:34
1

Add the following configuration in gradle.properties

//Turn off the resource compression that comes with the system
android.enableResourceOptimizations=false
pmmlee
  • 11
  • 1
  • `enableResourceOptimizations` will be removed in AGP 8.0, [source](https://github.com/godotengine/godot/issues/53749) (unfortunately I can't find anything more definitive). Also if anybody is interested, there is a [blog post by Jake Wharton about this flag](https://jakewharton.com/smaller-apks-with-resource-optimization/) – Sergei Kozelko Mar 24 '23 at 14:58
0

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"
Steve M
  • 9,296
  • 11
  • 49
  • 98