10

I'm experiencing somewhat unexpected behavior with ItemDecoration for RecyclerView elements.

On some phones (Samsung Android 5 devices), my ItemDecoration is not showing when proguard is applied with the build (minify true). Without proguard/minify it's working fine, you can see the ItemDecoration between the elements of the recycler.

On most phones, the issue does not exist, you can see the item decoration with or without proguard applied.

Not sure what happens there, but any input is appreciated.

The item decorator code:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;

public class DividerItemDecoration extends RecyclerView.ItemDecoration {
    private Drawable mDivider;

    public DividerItemDecoration(Context context) {
        mDivider = ContextCompat.getDrawable(context, R.drawable.line_divider);
    }

    @Override
    public void onDrawOver(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();

        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

            int top = child.getBottom() + params.bottomMargin;
            int bottom = top + mDivider.getIntrinsicHeight();
            int margin = 30;
            mDivider.setBounds(left + margin, top, right - margin, bottom);
            mDivider.draw(canvas);
        }
    }
}

line_divider.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <size
        android:width="1dp"
        android:height="1dp" />
    <solid android:color="#ffc6c6c6" />
</shape>

Proguard rules:

-keepclassmembers class fqcn.of.javascript.interface.for.webview {
   public *;
}

# support design library
-dontwarn android.support.design.**
-keep class android.support.design.** { *; }
-keep interface android.support.design.** { *; }
-keep public class android.support.design.R$* { *; }


#retrofit
-dontwarn retrofit.**
-keep class retrofit.** { *; }
-keep class com.myappspackage.catalog.** { *; }

#OKHttp
-dontwarn okio.**
-keep class okio.** { *; }

-dontwarn org.slf4j.**
-keep class org.slf4j.** { *; }

-keep class android.support.v7.** { *; }
-keep interface android.support.v7.** { *; }

-keepattributes Signature
-keepattributes Exceptions

#Google analytics
 -keep class com.google.android.gms.** { *; }
 -keep public class com.google.android.gms.**
 -dontwarn com.google.android.gms.**

Gradle build log:

Executing tasks: [clean, :app:generateReleaseSources]

Configuration on demand is an incubating feature.
:app:clean
:app:preBuild UP-TO-DATE
:app:preReleaseBuild UP-TO-DATE
:app:checkReleaseManifest
:app:preDebugBuild UP-TO-DATE
:app:prepareComAndroidSupportAppcompatV72311Library
:app:prepareComAndroidSupportCardviewV72311Library
:app:prepareComAndroidSupportDesign2311Library
:app:prepareComAndroidSupportRecyclerviewV72311Library
:app:prepareComAndroidSupportSupportV42311Library
:app:prepareComCrashlyticsSdkAndroidAnswers131Library
:app:prepareComCrashlyticsSdkAndroidBeta113Library
:app:prepareComCrashlyticsSdkAndroidCrashlytics251Library
:app:prepareComCrashlyticsSdkAndroidCrashlyticsCore234Library
:app:prepareComGoogleAndroidGmsPlayServicesAnalytics840Library
:app:prepareComGoogleAndroidGmsPlayServicesBase840Library
:app:prepareComGoogleAndroidGmsPlayServicesBasement840Library
:app:prepareComGoogleAndroidGmsPlayServicesGcm840Library
:app:prepareComGoogleAndroidGmsPlayServicesMeasurement840Library
:app:prepareDeHdodenhofCircleimageview130Library
:app:prepareIoFabricSdkAndroidFabric135Library
:app:prepareReleaseDependencies
:app:compileReleaseAidl
:app:compileReleaseRenderscript
:app:generateReleaseBuildConfig
:app:generateReleaseAssets UP-TO-DATE
:app:mergeReleaseAssets
:app:processReleaseManifest
:app:fabricGenerateResourcesRelease
:app:generateReleaseResValues UP-TO-DATE
:app:generateReleaseResources
:app:mergeReleaseResources
AAPT: /Users/aviran/Projects/app/src/main/res/drawable-xhdpi/ic_drawer.png: libpng warning: iCCP: Not recognizing known sRGB profile that has been edited
AAPT: /Users/aviran/Projects/app/src/main/res/drawable-hdpi/ic_drawer.png: libpng warning: iCCP: Not recognizing known sRGB profile that has been edited
AAPT: /Users/aviran/Projects/app/src/main/res/drawable-mdpi/ic_drawer.png: libpng warning: iCCP: Not recognizing known sRGB profile that has been edited
:app:processReleaseResources
:app:generateReleaseSources

BUILD SUCCESSFUL

Total time: 30.549 secs

Super weird solution

Adding Log.i(TAG, "decorating: " + i); inside the for loop, actually makes it draw the lines for each item. Putting it outside the for loop does not work. Any idea what the heck is going on there?

Aviran
  • 5,160
  • 7
  • 44
  • 76
  • The most important input you can possibly receive here: review your logcat output for a clue to what is missing (and then modify your proguard config to ensure it remains intact). – mah Jan 12 '16 at 17:00
  • @mah here's a pastebin of the logcat on samsung S5, I dont see anything that might be related, can you take a look? http://pastebin.com/wb9CaS79 (The package name of the app is com.company.myAppName) – Aviran Jan 13 '16 at 07:21
  • Which `RecyclerView` library version are you using? What's your `Proguard` configuration? Did you check the build log when `minify` is enabled? Thanks. – fasteque Jan 15 '16 at 07:16
  • Could you please provide the code that you are drawing the decoration with? Are you drawing it yourself or are you drawing with a drawable? – David Medenjak Jan 15 '16 at 19:20
  • I've added the code for the custom decorator – Aviran Jan 16 '16 at 08:32
  • To target more specifically the issue, try to use a drawable entirely generated from code, or using the drawable somewhere else and see if it's in either one of the two places (divider and the other place you just added it). You'll know if it's an issue with the code or the drawable. – Marc Plano-Lesay Jan 16 '16 at 08:38
  • @fastequedo which build log? The mapping file? The merger xml? – Aviran Jan 17 '16 at 08:29
  • The build log in the `gradle` console: do you see any `proguard` related warning? Did you specify any specific rule in your `proguard` file? – fasteque Jan 18 '16 at 07:27
  • @aviran, can you confirm that the ItemDecorator is indeed invoke - add a log into the onDrawOver method or something. Besides can you upload the line_divider too? Is it possible that for some configuration (XXHDPI / XXXHDPI) the drawable is messed up? – Samuil Yanovski Jan 18 '16 at 11:59
  • @aviran can you please show what are the rules you have given in proguard ? – user1140237 Jan 19 '16 at 07:47
  • @SamuilYanovski - added to question I dont think it's a resolution issue, since it is visible without proguard miniying. – Aviran Jan 19 '16 at 07:57
  • @user1140237 - added to question – Aviran Jan 19 '16 at 07:57
  • @fasteque I don't see anything related, I've added the gradle build log to the question. – Aviran Jan 19 '16 at 08:00
  • @aviran rathern giving answer i'll ask in comment did you tried by adding these two as a rule apart from the two which you have already given`-dontwarn android.support.v7.** -keep class android.support.v7.** { *; }` – user1140237 Jan 19 '16 at 08:04
  • @user1140237 adding those two rules to the current proguard config does not solve the issue. – Aviran Jan 19 '16 at 08:14
  • I've stumbeld upon a workaround, add it to the question, any idea what's going on there? – Aviran Jan 19 '16 at 09:27
  • As proposed here above, did you put a log in the `onDrawOver` method of your item decoration to see if it's present when you run the code on the S5 (or put a breakpoint)? The class is there, otherwise you would have an exception at runtime if it was missing in the APK. – fasteque Jan 19 '16 at 09:28
  • @fasteque putting a Log call in the onDrawOver call didn't have an effect (I see the Log entry but no decoration is presented. putting in inside the for loop on the other hand actually works. – Aviran Jan 19 '16 at 09:30
  • Weird, wild guess, maybe it has to do with Proguard optimization, but I don't get why the issue is reproducible on some devices only. Try to add `-dontoptimize`. Here you can search for "disappearing loops": https://stuff.mit.edu/afs/sipb/project/android/sdk/android-sdk-linux/tools/proguard/docs/index.html#manual/troubleshooting.html – fasteque Jan 19 '16 at 09:35

1 Answers1

0

This doesnt directly answer your question but might work. What you can do is in your proguard file make an entry

-keep class yourpakganame.itemdecorator
-keep public class * extends android.support.v7.widget.RecyclerView.ItemDecoration
-keep class android.support.v7.widget.RecyclerView

if above doesnt works try with

-keepattributes *Annotation*, InnerClasses, Signature

This way your whole code is obfuscated leaving out the item decorator which is not big code leak :P

ingsaurabh
  • 15,249
  • 7
  • 52
  • 81
  • ok keep one more entry for RecyclerView.ItemDecoration like in updated answer – ingsaurabh Jan 16 '16 at 08:49
  • Just tried it, doesn't work. I dont think the problem is with the ItemDecorator being obfoscated, something else gets lost in the way. – Aviran Jan 17 '16 at 08:09