Search code examples
androidproguard

onCloseSystemDialogs shrinkResources problem


I have an app which supports show overlay screen (using SYSTEM_ALERT_WINDOW permission).

I implemented KEYCODE_BACK and home press listener to remove its overlay view.

val wrapper = object : FrameLayout(this) {
                override fun dispatchKeyEvent(event: KeyEvent): Boolean {
                    return when (event.keyCode) {
                        KeyEvent.KEYCODE_BACK -> {
                            deleteContentView()
                            true
                        }
                        else -> {
                            super.dispatchKeyEvent(event)
                        }
                    }
                }

                //if pressed home key,
                fun onCloseSystemDialogs(reason: String) {
                    //The Code Want to Perform.
                    deleteContentView()
                }
            }
contentView = LayoutInflater.from(this).inflate(R.layout.layout_overlay, wrapper)

It works in debug mode with ProGuard or R8 is not activated. When i built release apk, this home press listener didn't not works.

I don't know onCloesSystemDialogs() is not be called by any other method in app, so I let KEYCODE_BACK call onCloseSystemDialogs, i think it won't be shrink anymore.

override fun dispatchKeyEvent(event: KeyEvent): Boolean {
                    return when (event.keyCode) {
                        KeyEvent.KEYCODE_BACK -> {
                            onCloseSystemDialogs("")
                            true
                        }
                        else -> {
                            super.dispatchKeyEvent(event)
                        }
                    }
                }

But it still not work. Anyway to let Proguard or R8 not shrink this part of code? Thanks.

This is my build.gradle

buildTypes {
        debug {
            applicationIdSuffix '.debug'
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            resValue "string", "app_name", "My app (Dev)"
        }
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            resValue "string", "app_name", "My app"
        }
    }

My ProGuard file

-keepattributes Signature
-keepattributes *Annotation*

##---------------Begin: proguard configuration for Gson  ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }

# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { <fields>; }

# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapter
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

# Prevent R8 from leaving Data object members always null
-keepclassmembers,allowobfuscation class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

##---------------End: proguard configuration for Gson  ----------

-keep class io.realm.annotations.RealmModule
-keep @io.realm.annotations.RealmModule class *
-keep class io.realm.internal.Keep
-keep @io.realm.internal.Keep class * { *; }
-dontwarn javax.**
-keepnames public class * extends io.realm.RealmObject
-dontwarn io.realm.**

Solution

  • Here is a working solution

    Add to proguard-rules:

    -keepclassmembers public class * {
        public void onCloseSystemDialogs(java.lang.String);
    }
    

    But for some reason only adding this rule to proguard isn't enough, it keeps marking onCloseSystemDialogs as unused code.

    So, create a new class

    public class MyFrameLayout extends FrameLayout {
        //place here default constructors
    
        public void onCloseSystemDialogs(String reason) {
        }
    }
    

    Then instantiate wraper like this:

    MyFrameLayout wrapper = new MyFrameLayout(ctx) {
            @Override
            public boolean dispatchKeyEvent(KeyEvent event) {
                if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                    //do your stuff
                    return true;
                }
    
                return super.dispatchKeyEvent(event);
            }
    
            @Override
            public void onCloseSystemDialogs(String reason) {
                if (reason.equals("homekey") /*|| reason.equals("recentapps")*/) {
                    //do your stuff
                }
            }
        };