1

I'm trying to use an ImageButton to display a resource, a .png as a clickable button. When I run my app in debug, the ImageButton sources the image correctly.

enter image description here

However, when I run the app in release mode the ImageButton doesn't display the drawable:

enter image description here

I create and populate my ImageButtons programmatically with:

    private void setupButtons() {

        FlexboxLayout layout = view.findViewById(R.id.telcosLayout);
        final Activity activity = getActivity(); 

        // Telcom is an enum
        for (final Telcom t : Telcom.values()) {
            ImageButton b = new ImageButton(activity);

            int id = getId(t.toString().toLowerCase().replace(" ", "_") + "_logo", R.drawable.class);
            Log.i(TAG, "id is " + id);
            b.setImageResource(id);

            layout.addView(b);

            b.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    scanButtonListener.onShowScanButton(t);
                }
            });

        }
    }

And the output of my logs when run in release mode is:

2019-10-13 11:07:49.500 25757-25757/? I/select telcome: id is 2131165284
2019-10-13 11:07:49.501 25757-25757/? I/select telcome: id is 2131165320

And here are the logs from running the app in debug mode:

2019-10-13 11:12:22.575 26146-26146/com.glan.input I/select telcome: id is 2131165284
2019-10-13 11:12:22.583 26146-26146/com.glan.input I/select telcome: id is 2131165320

It seems the same drawables are being found in both modes but for some reason they won't display in release mode. What is going on?

I've verified that the drawable exists for all the screen densities from drawable-ldpi to drawable-xxxhdpi.

I've also found that if I hardcode b.setImageResource(2131165284); based on the log lines, the ImageButton displays the same image for both buttons in both debug and release mode, which is expected behavior.

enter image description here

How come dynamically setting the resource doesn't work in release mode?

EDIT: Ok, I think I found the problem. My release build mode has the following properties:

        release {
            minifyEnabled true
            shrinkResources true
            debuggable true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
            signingConfig = signingConfigs.release
        }

When I disabled shrinkResources, by commenting it out, the images appeared again. It seems that, based on "minifyEnabled" vs "shrinkResources" - what's the difference? and how to get the saved space?, ProGuard detects that the resources I depend, the .png drawables, on aren't used because they're dynamically requested and so shrinkResources removes them entirely.

Does anyone know how to get around this?

Paymahn Moghadasian
  • 9,301
  • 13
  • 56
  • 94

2 Answers2

0

Ok, I found the answer. The solution that worked for me was to use tools:keep from https://developer.android.com/studio/write/tool-attributes#toolskeep to purposefully keep those resources even with shrinkResources set to true.

See also https://stackoverflow.com/a/50703322/1489726

Paymahn Moghadasian
  • 9,301
  • 13
  • 56
  • 94
0

Have you checked if its happening because the image is taking up too many resources? How large is the image file? Is it the same dimension as the button?

Android will not allow the app in release mode to take so many resources. I'd suggest you use a library like Picasso for setting the image resource on the ImageButton. Picasso will handle the resizing of the resource for the screen and button size itself.

And it's very easy to use as well.

Picasso.get().load(R.drawable.your_image_resource).into(yourImageButton);

https://square.github.io/picasso/

Chiranjeev Jain
  • 89
  • 3
  • 10