androidproguardandroid-resourcesshrinkresources

Android: Make "shrinkResources true" to keep all drawables, but remove other unused resources


I have a project which contains a lot of drawables, which are named starting with "a" or "b" (For example a1_back, a2_back, b1_start, b2_start and many-many more). Those drawables are not used in code, but used by the following code:

String name = image.getName();//getName() returns for examle "a1_back"
res = getResources().getIdentifier(name, "drawable", getPackageName());

So, nowhere in code do I have specific string "a1_back" used. That's why when I set "shrinkResources true" all my drawables starting with "a" and "b" are removed.

I've read that you can specify what resources to keep using following xml file:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@layout/l_used_c"
    tools:discard="@layout/unused2" />

But I have way to many drawables and don't want to specify each one separately. Is there a way to set a pattern in "tools:keep"(to keep all drawables starting with "a" or "b") or maybe make it keep all drawables in project, but remove other unused resources?

Thanks in advance! :)


Solution

  • There is a workaround you can use. Add a prefix for all drawables which you want to keep

    @Nullable
    private Drawable getDrawableByName(@NonNull final Context context, @NonNull final String name) {
        final String prefixName = String.format("prefix_%s", name);
        return getDrawable(context, prefixName);
    }
    
    @Nullable
    protected Drawable getDrawable(@NonNull final Context context, @NonNull final String name) {
        final Resources resources = context.getResources();
        final int resourceId = resources.getIdentifier(name, "drawable", context.getPackageName());
        try {
            return resources.getDrawable(resourceId, context.getTheme());
        } catch (final Resources.NotFoundException exception) {
            return null;
        }
    }
    

    The trick here

    final String prefixName = String.format("prefix_%s", name);
    

    Resource shrinking mechanism analyzes that all drawables with "prefix_" can be used and it doesn't touch these files.