From 77a727a22b32d1c7a06eb1180be59d91f7c3e076 Mon Sep 17 00:00:00 2001 From: fornewid Date: Sun, 27 Sep 2026 18:56:55 +0900 Subject: [PATCH 1/2] Add proguard-shield --- .github/workflows/build.yaml | 3 + CHECK.md | 10 + app/build.gradle | 5 + app/proguardShield/releaseFastRules.txt | 451 ++++++++++++++++++++++++ app/proguardShield/releaseRules.txt | 451 ++++++++++++++++++++++++ build.gradle | 1 + check.sh | 16 +- gradle/libs.versions.toml | 2 + 8 files changed, 934 insertions(+), 5 deletions(-) create mode 100644 app/proguardShield/releaseFastRules.txt create mode 100644 app/proguardShield/releaseRules.txt diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index dd7616b5..9ba983e1 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -34,6 +34,9 @@ jobs: - name: Check manifestShield run: ./gradlew manifestShield + - name: Check proguardShield + run: ./gradlew proguardShieldFast + - name: Check spotless run: ./gradlew spotlessCheck --init-script gradle/init.gradle.kts --stacktrace diff --git a/CHECK.md b/CHECK.md index a6f8bf29..083c4b6f 100644 --- a/CHECK.md +++ b/CHECK.md @@ -18,6 +18,11 @@ ./gradlew manifestShield ``` +- proguardShield +```bash +./gradlew proguardShieldFast +``` + - spotless ```bash ./gradlew spotlessCheck --init-script gradle/init.gradle.kts @@ -40,6 +45,11 @@ ./gradlew manifestShieldBaseline ``` +- proguardShield +```bash +./gradlew proguardShieldBaseline +``` + - spotless ```bash ./gradlew spotlessApply --init-script gradle/init.gradle.kts diff --git a/app/build.gradle b/app/build.gradle index 4aee7072..835dab07 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,6 +5,7 @@ plugins { id "org.jetbrains.kotlin.plugin.serialization" alias libs.plugins.dependencyGuard alias libs.plugins.manifestShield + alias libs.plugins.proguardShield alias(libs.plugins.baselineprofile) } @@ -141,6 +142,10 @@ manifestShield { configuration("release") } +proguardShield { + configuration("release") +} + task applyDependencyBaseline { dependsOn "dependencyGuardBaseline" } diff --git a/app/proguardShield/releaseFastRules.txt b/app/proguardShield/releaseFastRules.txt new file mode 100644 index 00000000..6ecb65fa --- /dev/null +++ b/app/proguardShield/releaseFastRules.txt @@ -0,0 +1,451 @@ +-allowaccessmodification +-assumenosideeffects class androidx.datastore.core.SharedCounter$Factory { +private boolean isDalvik() return true; +} +-assumenosideeffects class androidx.startup.StartupLogger { public static ; } +-assumenosideeffects class kotlinx.coroutines.DebugKt { +boolean getASSERTIONS_ENABLED() return false; +boolean getDEBUG() return false; +boolean getRECOVER_STACK_TRACES() return false; +} +-assumenosideeffects class kotlinx.coroutines.internal.FastServiceLoaderKt { +boolean ANDROID_DETECTED return true; +} +-assumenosideeffects class kotlinx.coroutines.internal.MainDispatcherLoader { +boolean FAST_SERVICE_LOADER_ENABLED return false; +} +-assumenosideeffects class kotlinx.coroutines.internal.MainDispatchersKt { +boolean SUPPORT_MISSING return false; +} +-assumenosideeffects public class androidx.compose.runtime.Composer { +void (); +} +-assumenosideeffects public class androidx.compose.runtime.ComposerImpl { +void (); +} +-assumenosideeffects public class androidx.compose.runtime.ComposerKt { +void sourceInformation(androidx.compose.runtime.Composer,java.lang.String); +void sourceInformationMarkerStart(androidx.compose.runtime.Composer,int,java.lang.String); +void sourceInformationMarkerEnd(androidx.compose.runtime.Composer); +} +-assumevalues class androidx.compose.runtime.tooling.ComposeStackTraceMode { +private static boolean isMinified return true; +} +-dontnote android.net.http.** +-dontnote android.support.** +-dontnote androidx.** +-dontnote com.android.vending.licensing.ILicensingService +-dontnote com.google.android.vending.licensing.ILicensingService +-dontnote com.google.vending.licensing.ILicensingService +-dontnote java.lang.invoke.** +-dontnote kotlinx.serialization.** +-dontnote kotlinx.serialization.SerializationKt +-dontnote org.apache.http.** +-dontwarn android.support.** +-dontwarn android.support.** +-dontwarn android.view.DisplayListCanvas +-dontwarn android.view.HardwareCanvas +-dontwarn android.view.RenderNode +-dontwarn androidx.** +-dontwarn androidx.** +-dontwarn androidx.lifecycle.LiveData +-dontwarn androidx.room.paging.** +-dontwarn coil3.PlatformContext +-dontwarn com.crashlytics.** +-dontwarn com.google.errorprone.annotations.* +-dontwarn java.lang.ClassValue +-dontwarn java.lang.instrument.ClassFileTransformer +-dontwarn java.lang.instrument.Instrumentation +-dontwarn javax.annotation.** +-dontwarn javax.annotation.** +-dontwarn kotlin.Unit +-dontwarn kotlinx.serialization.internal.ClassValueReferences +-dontwarn okhttp3.internal.platform.** +-dontwarn org.bouncycastle.** +-dontwarn org.codehaus.mojo.animal_sniffer.* +-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement +-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement +-dontwarn org.conscrypt.** +-dontwarn org.jetbrains.annotations.** +-dontwarn org.jetbrains.annotations.** +-dontwarn org.openjsse.** +-dontwarn retrofit2.KotlinExtensions +-dontwarn retrofit2.KotlinExtensions$* +-dontwarn soup.movie.log.Logger +-dontwarn sun.misc.Signal +-dontwarn sun.misc.SignalHandler +-identifiernamestring @dagger.internal.IdentifierNameString class ** { +static java.lang.String *; +} +-if @kotlinx.serialization.Serializable class ** +-if @kotlinx.serialization.Serializable class ** +-if @kotlinx.serialization.Serializable class ** { +public static ** INSTANCE; +} +-if @kotlinx.serialization.Serializable class ** { +static **$* *; +} +-if @kotlinx.serialization.internal.NamedCompanion class * +-if class androidx.window.layout.adapter.sidecar.SidecarCompat { +public *** setExtensionCallback(androidx.window.layout.adapter.sidecar.ExtensionInterfaceCompat$ExtensionCallbackInterface); +} +-if interface * { @retrofit2.http.* ; } +-if interface * { @retrofit2.http.* ; } +-if interface * { @retrofit2.http.* public *** *(...); } +-if public class ** extends androidx.fragment.app.Fragment +-if public class androidx.compose.ui.platform.AndroidCompositionLocals_androidKt { +public static *** getLocalLifecycleOwner(); +} +-if public class androidx.compose.ui.platform.AndroidCompositionLocals_androidKt { +public static *** getLocalSavedStateRegistryOwner(); +} +-keep @android.support.annotation.Keep class * {*;} +-keep @androidx.annotation.Keep class * {*;} +-keep class * extends androidx.room.RoomDatabase { void (); } +-keep class * extends androidx.startup.Initializer { +(); +} +-keep class * implements androidx.lifecycle.GeneratedAdapter { +(...); +} +-keep class * implements androidx.versionedparcelable.VersionedParcelable +-keep class android.support.annotation.Keep +-keep class android.widget.Space { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.app.AlertController$RecycleListView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.view.menu.ActionMenuItemView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.view.menu.ExpandedMenuView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.view.menu.ListMenuItemView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ActionBarContainer { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ActionBarContextView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ActionBarOverlayLayout { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ActionMenuView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ActivityChooserView$InnerLayout { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.AlertDialogLayout { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ButtonBarLayout { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ContentFrameLayout { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.DialogTitle { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.FitWindowsFrameLayout { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.FitWindowsLinearLayout { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.SearchView$SearchAutoComplete { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.Toolbar { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ViewStubCompat { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.browser.browseractions.BrowserActionsFallbackMenuView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.core.app.CoreComponentFactory { (); } +-keep class androidx.core.widget.NestedScrollView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.profileinstaller.ProfileInstallReceiver { (); } +-keep class androidx.room.MultiInstanceInvalidationService { (); } +-keep class androidx.startup.InitializationProvider { (); } +-keep class androidx.window.layout.adapter.sidecar.SidecarCompat$TranslatingCallback, +androidx.window.layout.adapter.sidecar.DistinctElementSidecarCallback { +public *** onDeviceStateChanged(androidx.window.sidecar.SidecarDeviceState); +public *** onWindowLayoutChanged(android.os.IBinder, androidx.window.sidecar.SidecarWindowLayoutInfo); +} +-keep class androidx.work.WorkerParameters +-keep class androidx.work.impl.background.systemalarm.RescheduleReceiver { (); } +-keep class androidx.work.impl.background.systemjob.SystemJobService { (); } +-keep class androidx.work.impl.diagnostics.DiagnosticsReceiver { (); } +-keep class androidx.work.impl.foreground.SystemForegroundService { (); } +-keep class androidx.work.impl.utils.ForceStopRunnable$BroadcastReceiver { (); } +-keep class com.crashlytics.** { *; } +-keep class kotlin.Metadata { *; } +-keep class soup.movie.MovieApplication { (); } +-keep class soup.movie.data.database.internal.entity.** { *; } +-keep class soup.movie.data.network.response.** { *; } +-keep class soup.movie.ui.main.MainActivity { (); } +-keep interface androidx.window.area.reflectionguard.* {*;} +-keep interface androidx.window.reflection.Consumer2 { +public *** accept(***); +} +-keep interface androidx.window.reflection.JFunction2 { +public *** apply(***); +} +-keep interface androidx.window.reflection.Predicate2 { +public *** test(***); +} +-keep public class android.support.**Parcelizer { *; } +-keep public class androidx.**Parcelizer { *; } +-keep public class androidx.compose.ui.platform.AndroidCompositionLocals_androidKt { +public static *** getLocalLifecycleOwner(); +} +-keep public class androidx.compose.ui.platform.AndroidCompositionLocals_androidKt { +public static *** getLocalSavedStateRegistryOwner(); +} +-keep public class androidx.versionedparcelable.ParcelImpl +-keep public class com.android.vending.licensing.ILicensingService +-keep public class com.google.android.vending.licensing.ILicensingService +-keep public class com.google.vending.licensing.ILicensingService +-keep, allowshrinking, allowoptimization, allowobfuscation, allowaccessmodification class <1> +-keep,allowobfuscation @interface androidx.annotation.Keep +-keep,allowobfuscation interface * extends <1> +-keep,allowobfuscation interface <1> +-keep,allowobfuscation,allowshrinking @dagger.hilt.EntryPoint class * +-keep,allowobfuscation,allowshrinking @dagger.hilt.android.EarlyEntryPoint class * +-keep,allowobfuscation,allowshrinking @dagger.hilt.internal.ComponentEntryPoint class * +-keep,allowobfuscation,allowshrinking @dagger.hilt.internal.GeneratedEntryPoint class * +-keep,allowobfuscation,allowshrinking class * extends androidx.compose.ui.node.ModifierNodeElement +-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation +-keep,allowobfuscation,allowshrinking class retrofit2.Response +-keep,allowobfuscation,allowshrinking class soup.movie.feature.detail.impl.DetailViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.detail.impl.DetailViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.HomeViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.HomeViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.favorite.HomeFavoriteViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.favorite.HomeFavoriteViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.filter.HomeFilterViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.filter.HomeFilterViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.now.HomeNowViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.now.HomeNowViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.plan.HomePlanViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.plan.HomePlanViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.search.impl.SearchViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.search.impl.SearchViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.settings.impl.home.SettingsViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.settings.impl.home.SettingsViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.settings.impl.theme.ThemeOptionViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.settings.impl.theme.ThemeOptionViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.ui.main.MainViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.ui.main.MainViewModel +-keep,allowoptimization,allowshrinking,allowobfuscation class <3> +-keep,allowshrinking class androidx.window.layout.adapter.extensions.MulticastConsumer { +void accept(androidx.window.extensions.layout.WindowLayoutInfo); +} +-keep,includedescriptorclasses class soup.movie.**$$serializer { *; } +-keepattributes *Annotation*, InnerClasses +-keepattributes AnnotationDefault +-keepattributes AnnotationDefault, +EnclosingMethod, +InnerClasses, +RuntimeVisibleAnnotations, +RuntimeVisibleParameterAnnotations, +RuntimeVisibleTypeAnnotations, +Signature +-keepattributes AnnotationDefault, +RuntimeVisibleAnnotations, +RuntimeVisibleParameterAnnotations, +RuntimeVisibleTypeAnnotations +-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations +-keepattributes RuntimeVisibleAnnotations,AnnotationDefault +-keepattributes Signature, InnerClasses, EnclosingMethod +-keepclasseswithmembernames,includedescriptorclasses class * { +native ; +} +-keepclasseswithmembernames,includedescriptorclasses class androidx.datastore.core.NativeSharedCounter { +native ; +} +-keepclasseswithmembers class * { +@android.support.annotation.Keep ; +} +-keepclasseswithmembers class * { +@android.support.annotation.Keep (...); +} +-keepclasseswithmembers class * { +@android.support.annotation.Keep ; +} +-keepclasseswithmembers class * { +@androidx.annotation.Keep ; +} +-keepclasseswithmembers class * { +@androidx.annotation.Keep (...); +} +-keepclasseswithmembers class * { +@androidx.annotation.Keep ; +} +-keepclasseswithmembers class androidx.graphics.path.** { +native ; +} +-keepclasseswithmembers class soup.movie.** { +kotlinx.serialization.KSerializer serializer(...); +} +-keepclasseswithmembers,allowobfuscation public class <1> { +public (); +} +-keepclasseswithmembers,allowobfuscation public class androidx.lifecycle.ReportFragment { +public (); +} +-keepclassmembernames class * { +static <1> *; +} +-keepclassmembernames,allowobfuscation,allowshrinking class androidx.appcompat.widget.AppCompatTextViewAutoSizeHelper$Impl* { +; +} +-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.app.NotificationCompat$*$Api*Impl { +; +} +-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.os.UserHandleCompat$Api*Impl { +; +} +-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.view.ViewCompat$Api* { +; +} +-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.view.WindowInsetsCompat$*Impl* { +; +} +-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.widget.EdgeEffectCompat$Api*Impl { +; +} +-keepclassmembers @kotlinx.serialization.Serializable class ** { +public static ** INSTANCE; +kotlinx.serialization.KSerializer serializer(...); +} +-keepclassmembers class * extends android.app.Activity { +public void *(android.view.View); +} +-keepclassmembers class * extends androidx.datastore.preferences.protobuf.GeneratedMessageLite { +; +} +-keepclassmembers class * extends androidx.lifecycle.EmptyActivityLifecycleCallbacks { *; } +-keepclassmembers class * extends androidx.work.InputMerger { void (); } +-keepclassmembers class * implements android.os.Parcelable { +public static final ** CREATOR; +} +-keepclassmembers class * { +@android.webkit.JavascriptInterface ; +} +-keepclassmembers class ** { +@androidx.lifecycle.OnLifecycleEvent *; +} +-keepclassmembers class <1> { +public static <1> INSTANCE; +kotlinx.serialization.KSerializer serializer(...); +} +-keepclassmembers class <1> { +static <1>$* Companion; +} +-keepclassmembers class <2>$<3> { +kotlinx.serialization.KSerializer serializer(...); +} +-keepclassmembers class androidx.compose.ui.graphics.layer.view.PlaceholderHardwareCanvas { +public int drawRenderNode(...); +public boolean isHardwareAccelerated(); +} +-keepclassmembers class androidx.compose.ui.graphics.layer.view.ViewLayerContainer { +protected void dispatchGetDisplayList(); +} +-keepclassmembers class androidx.compose.ui.platform.AndroidComposeView { +android.view.View findViewByAccessibilityIdTraversal(int); +} +-keepclassmembers class androidx.compose.ui.platform.ViewLayerContainer { +protected void dispatchGetDisplayList(); +} +-keepclassmembers class androidx.lifecycle.ReportFragment$LifecycleCallbacks { *; } +-keepclassmembers class androidx.transition.ChangeBounds$* extends android.animation.AnimatorListenerAdapter { +androidx.transition.ChangeBounds$ViewBounds mViewBounds; +} +-keepclassmembers class androidx.vectordrawable.graphics.drawable.VectorDrawableCompat$* { +void set*(***); +*** get*(); +} +-keepclassmembers class kotlin.coroutines.SafeContinuation { +volatile ; +} +-keepclassmembers class kotlinx.coroutines.** { +volatile ; +} +-keepclassmembers class soup.movie.** { +*** Companion; +} +-keepclassmembers enum * { +public static **[] values(); +public static ** valueOf(java.lang.String); +} +-keepclassmembers enum androidx.lifecycle.Lifecycle$Event { +; +} +-keepclassmembers public class * extends android.view.View { +void set*(***); +*** get*(); +} +-keepclassmembers public class * extends androidx.work.ListenableWorker { +public (...); +} +-keepclassmembers public class **$$serializer { +private ** descriptor; +} +-keepclassmembers,allowobfuscation class * extends androidx.lifecycle.AndroidViewModel { +(android.app.Application); +} +-keepclassmembers,allowobfuscation class * extends androidx.lifecycle.AndroidViewModel { +(android.app.Application,androidx.lifecycle.SavedStateHandle); +} +-keepclassmembers,allowobfuscation class * extends androidx.lifecycle.ViewModel { +(); +} +-keepclassmembers,allowobfuscation class * extends androidx.lifecycle.ViewModel { +(androidx.lifecycle.SavedStateHandle); +} +-keepclassmembers,allowobfuscation class * implements androidx.savedstate.SavedStateRegistry$AutoRecreated { +(); +} +-keepclassmembers,allowobfuscation class * { +@androidx.annotation.DoNotInline ; +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static java.lang.Void throw*Exception(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +static java.lang.String exceptionMessage*(...); +java.lang.String exceptionMessage*(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.runtime.** { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +static java.lang.String exceptionMessage*(...); +java.lang.String exceptionMessage*(...); +static void compose*RuntimeError(...); +static java.lang.Void compose*RuntimeError(...); +} +-keepclassmembers,allowshrinking,allowobfuscation interface * { +@retrofit2.http.* ; +} +-keepnames @androidx.hilt.work.HiltWorker class * extends androidx.work.ListenableWorker +-keepnames @kotlinx.serialization.internal.NamedCompanion class * +-keepnames class * extends androidx.startup.Initializer +-keepnames class * extends androidx.work.InputMerger +-keepnames class * extends androidx.work.ListenableWorker +-keepnames class androidx.compose.ui.input.pointer.PointerInputEventHandler { +*; +} +-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase diff --git a/app/proguardShield/releaseRules.txt b/app/proguardShield/releaseRules.txt new file mode 100644 index 00000000..6ecb65fa --- /dev/null +++ b/app/proguardShield/releaseRules.txt @@ -0,0 +1,451 @@ +-allowaccessmodification +-assumenosideeffects class androidx.datastore.core.SharedCounter$Factory { +private boolean isDalvik() return true; +} +-assumenosideeffects class androidx.startup.StartupLogger { public static ; } +-assumenosideeffects class kotlinx.coroutines.DebugKt { +boolean getASSERTIONS_ENABLED() return false; +boolean getDEBUG() return false; +boolean getRECOVER_STACK_TRACES() return false; +} +-assumenosideeffects class kotlinx.coroutines.internal.FastServiceLoaderKt { +boolean ANDROID_DETECTED return true; +} +-assumenosideeffects class kotlinx.coroutines.internal.MainDispatcherLoader { +boolean FAST_SERVICE_LOADER_ENABLED return false; +} +-assumenosideeffects class kotlinx.coroutines.internal.MainDispatchersKt { +boolean SUPPORT_MISSING return false; +} +-assumenosideeffects public class androidx.compose.runtime.Composer { +void (); +} +-assumenosideeffects public class androidx.compose.runtime.ComposerImpl { +void (); +} +-assumenosideeffects public class androidx.compose.runtime.ComposerKt { +void sourceInformation(androidx.compose.runtime.Composer,java.lang.String); +void sourceInformationMarkerStart(androidx.compose.runtime.Composer,int,java.lang.String); +void sourceInformationMarkerEnd(androidx.compose.runtime.Composer); +} +-assumevalues class androidx.compose.runtime.tooling.ComposeStackTraceMode { +private static boolean isMinified return true; +} +-dontnote android.net.http.** +-dontnote android.support.** +-dontnote androidx.** +-dontnote com.android.vending.licensing.ILicensingService +-dontnote com.google.android.vending.licensing.ILicensingService +-dontnote com.google.vending.licensing.ILicensingService +-dontnote java.lang.invoke.** +-dontnote kotlinx.serialization.** +-dontnote kotlinx.serialization.SerializationKt +-dontnote org.apache.http.** +-dontwarn android.support.** +-dontwarn android.support.** +-dontwarn android.view.DisplayListCanvas +-dontwarn android.view.HardwareCanvas +-dontwarn android.view.RenderNode +-dontwarn androidx.** +-dontwarn androidx.** +-dontwarn androidx.lifecycle.LiveData +-dontwarn androidx.room.paging.** +-dontwarn coil3.PlatformContext +-dontwarn com.crashlytics.** +-dontwarn com.google.errorprone.annotations.* +-dontwarn java.lang.ClassValue +-dontwarn java.lang.instrument.ClassFileTransformer +-dontwarn java.lang.instrument.Instrumentation +-dontwarn javax.annotation.** +-dontwarn javax.annotation.** +-dontwarn kotlin.Unit +-dontwarn kotlinx.serialization.internal.ClassValueReferences +-dontwarn okhttp3.internal.platform.** +-dontwarn org.bouncycastle.** +-dontwarn org.codehaus.mojo.animal_sniffer.* +-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement +-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement +-dontwarn org.conscrypt.** +-dontwarn org.jetbrains.annotations.** +-dontwarn org.jetbrains.annotations.** +-dontwarn org.openjsse.** +-dontwarn retrofit2.KotlinExtensions +-dontwarn retrofit2.KotlinExtensions$* +-dontwarn soup.movie.log.Logger +-dontwarn sun.misc.Signal +-dontwarn sun.misc.SignalHandler +-identifiernamestring @dagger.internal.IdentifierNameString class ** { +static java.lang.String *; +} +-if @kotlinx.serialization.Serializable class ** +-if @kotlinx.serialization.Serializable class ** +-if @kotlinx.serialization.Serializable class ** { +public static ** INSTANCE; +} +-if @kotlinx.serialization.Serializable class ** { +static **$* *; +} +-if @kotlinx.serialization.internal.NamedCompanion class * +-if class androidx.window.layout.adapter.sidecar.SidecarCompat { +public *** setExtensionCallback(androidx.window.layout.adapter.sidecar.ExtensionInterfaceCompat$ExtensionCallbackInterface); +} +-if interface * { @retrofit2.http.* ; } +-if interface * { @retrofit2.http.* ; } +-if interface * { @retrofit2.http.* public *** *(...); } +-if public class ** extends androidx.fragment.app.Fragment +-if public class androidx.compose.ui.platform.AndroidCompositionLocals_androidKt { +public static *** getLocalLifecycleOwner(); +} +-if public class androidx.compose.ui.platform.AndroidCompositionLocals_androidKt { +public static *** getLocalSavedStateRegistryOwner(); +} +-keep @android.support.annotation.Keep class * {*;} +-keep @androidx.annotation.Keep class * {*;} +-keep class * extends androidx.room.RoomDatabase { void (); } +-keep class * extends androidx.startup.Initializer { +(); +} +-keep class * implements androidx.lifecycle.GeneratedAdapter { +(...); +} +-keep class * implements androidx.versionedparcelable.VersionedParcelable +-keep class android.support.annotation.Keep +-keep class android.widget.Space { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.app.AlertController$RecycleListView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.view.menu.ActionMenuItemView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.view.menu.ExpandedMenuView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.view.menu.ListMenuItemView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ActionBarContainer { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ActionBarContextView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ActionBarOverlayLayout { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ActionMenuView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ActivityChooserView$InnerLayout { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.AlertDialogLayout { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ButtonBarLayout { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ContentFrameLayout { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.DialogTitle { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.FitWindowsFrameLayout { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.FitWindowsLinearLayout { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.SearchView$SearchAutoComplete { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.Toolbar { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.appcompat.widget.ViewStubCompat { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.browser.browseractions.BrowserActionsFallbackMenuView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.core.app.CoreComponentFactory { (); } +-keep class androidx.core.widget.NestedScrollView { (android.content.Context, android.util.AttributeSet); } +-keep class androidx.profileinstaller.ProfileInstallReceiver { (); } +-keep class androidx.room.MultiInstanceInvalidationService { (); } +-keep class androidx.startup.InitializationProvider { (); } +-keep class androidx.window.layout.adapter.sidecar.SidecarCompat$TranslatingCallback, +androidx.window.layout.adapter.sidecar.DistinctElementSidecarCallback { +public *** onDeviceStateChanged(androidx.window.sidecar.SidecarDeviceState); +public *** onWindowLayoutChanged(android.os.IBinder, androidx.window.sidecar.SidecarWindowLayoutInfo); +} +-keep class androidx.work.WorkerParameters +-keep class androidx.work.impl.background.systemalarm.RescheduleReceiver { (); } +-keep class androidx.work.impl.background.systemjob.SystemJobService { (); } +-keep class androidx.work.impl.diagnostics.DiagnosticsReceiver { (); } +-keep class androidx.work.impl.foreground.SystemForegroundService { (); } +-keep class androidx.work.impl.utils.ForceStopRunnable$BroadcastReceiver { (); } +-keep class com.crashlytics.** { *; } +-keep class kotlin.Metadata { *; } +-keep class soup.movie.MovieApplication { (); } +-keep class soup.movie.data.database.internal.entity.** { *; } +-keep class soup.movie.data.network.response.** { *; } +-keep class soup.movie.ui.main.MainActivity { (); } +-keep interface androidx.window.area.reflectionguard.* {*;} +-keep interface androidx.window.reflection.Consumer2 { +public *** accept(***); +} +-keep interface androidx.window.reflection.JFunction2 { +public *** apply(***); +} +-keep interface androidx.window.reflection.Predicate2 { +public *** test(***); +} +-keep public class android.support.**Parcelizer { *; } +-keep public class androidx.**Parcelizer { *; } +-keep public class androidx.compose.ui.platform.AndroidCompositionLocals_androidKt { +public static *** getLocalLifecycleOwner(); +} +-keep public class androidx.compose.ui.platform.AndroidCompositionLocals_androidKt { +public static *** getLocalSavedStateRegistryOwner(); +} +-keep public class androidx.versionedparcelable.ParcelImpl +-keep public class com.android.vending.licensing.ILicensingService +-keep public class com.google.android.vending.licensing.ILicensingService +-keep public class com.google.vending.licensing.ILicensingService +-keep, allowshrinking, allowoptimization, allowobfuscation, allowaccessmodification class <1> +-keep,allowobfuscation @interface androidx.annotation.Keep +-keep,allowobfuscation interface * extends <1> +-keep,allowobfuscation interface <1> +-keep,allowobfuscation,allowshrinking @dagger.hilt.EntryPoint class * +-keep,allowobfuscation,allowshrinking @dagger.hilt.android.EarlyEntryPoint class * +-keep,allowobfuscation,allowshrinking @dagger.hilt.internal.ComponentEntryPoint class * +-keep,allowobfuscation,allowshrinking @dagger.hilt.internal.GeneratedEntryPoint class * +-keep,allowobfuscation,allowshrinking class * extends androidx.compose.ui.node.ModifierNodeElement +-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation +-keep,allowobfuscation,allowshrinking class retrofit2.Response +-keep,allowobfuscation,allowshrinking class soup.movie.feature.detail.impl.DetailViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.detail.impl.DetailViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.HomeViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.HomeViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.favorite.HomeFavoriteViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.favorite.HomeFavoriteViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.filter.HomeFilterViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.filter.HomeFilterViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.now.HomeNowViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.now.HomeNowViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.plan.HomePlanViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.plan.HomePlanViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.search.impl.SearchViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.search.impl.SearchViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.settings.impl.home.SettingsViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.settings.impl.home.SettingsViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.settings.impl.theme.ThemeOptionViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.feature.settings.impl.theme.ThemeOptionViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.ui.main.MainViewModel +-keep,allowobfuscation,allowshrinking class soup.movie.ui.main.MainViewModel +-keep,allowoptimization,allowshrinking,allowobfuscation class <3> +-keep,allowshrinking class androidx.window.layout.adapter.extensions.MulticastConsumer { +void accept(androidx.window.extensions.layout.WindowLayoutInfo); +} +-keep,includedescriptorclasses class soup.movie.**$$serializer { *; } +-keepattributes *Annotation*, InnerClasses +-keepattributes AnnotationDefault +-keepattributes AnnotationDefault, +EnclosingMethod, +InnerClasses, +RuntimeVisibleAnnotations, +RuntimeVisibleParameterAnnotations, +RuntimeVisibleTypeAnnotations, +Signature +-keepattributes AnnotationDefault, +RuntimeVisibleAnnotations, +RuntimeVisibleParameterAnnotations, +RuntimeVisibleTypeAnnotations +-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations +-keepattributes RuntimeVisibleAnnotations,AnnotationDefault +-keepattributes Signature, InnerClasses, EnclosingMethod +-keepclasseswithmembernames,includedescriptorclasses class * { +native ; +} +-keepclasseswithmembernames,includedescriptorclasses class androidx.datastore.core.NativeSharedCounter { +native ; +} +-keepclasseswithmembers class * { +@android.support.annotation.Keep ; +} +-keepclasseswithmembers class * { +@android.support.annotation.Keep (...); +} +-keepclasseswithmembers class * { +@android.support.annotation.Keep ; +} +-keepclasseswithmembers class * { +@androidx.annotation.Keep ; +} +-keepclasseswithmembers class * { +@androidx.annotation.Keep (...); +} +-keepclasseswithmembers class * { +@androidx.annotation.Keep ; +} +-keepclasseswithmembers class androidx.graphics.path.** { +native ; +} +-keepclasseswithmembers class soup.movie.** { +kotlinx.serialization.KSerializer serializer(...); +} +-keepclasseswithmembers,allowobfuscation public class <1> { +public (); +} +-keepclasseswithmembers,allowobfuscation public class androidx.lifecycle.ReportFragment { +public (); +} +-keepclassmembernames class * { +static <1> *; +} +-keepclassmembernames,allowobfuscation,allowshrinking class androidx.appcompat.widget.AppCompatTextViewAutoSizeHelper$Impl* { +; +} +-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.app.NotificationCompat$*$Api*Impl { +; +} +-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.os.UserHandleCompat$Api*Impl { +; +} +-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.view.ViewCompat$Api* { +; +} +-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.view.WindowInsetsCompat$*Impl* { +; +} +-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.widget.EdgeEffectCompat$Api*Impl { +; +} +-keepclassmembers @kotlinx.serialization.Serializable class ** { +public static ** INSTANCE; +kotlinx.serialization.KSerializer serializer(...); +} +-keepclassmembers class * extends android.app.Activity { +public void *(android.view.View); +} +-keepclassmembers class * extends androidx.datastore.preferences.protobuf.GeneratedMessageLite { +; +} +-keepclassmembers class * extends androidx.lifecycle.EmptyActivityLifecycleCallbacks { *; } +-keepclassmembers class * extends androidx.work.InputMerger { void (); } +-keepclassmembers class * implements android.os.Parcelable { +public static final ** CREATOR; +} +-keepclassmembers class * { +@android.webkit.JavascriptInterface ; +} +-keepclassmembers class ** { +@androidx.lifecycle.OnLifecycleEvent *; +} +-keepclassmembers class <1> { +public static <1> INSTANCE; +kotlinx.serialization.KSerializer serializer(...); +} +-keepclassmembers class <1> { +static <1>$* Companion; +} +-keepclassmembers class <2>$<3> { +kotlinx.serialization.KSerializer serializer(...); +} +-keepclassmembers class androidx.compose.ui.graphics.layer.view.PlaceholderHardwareCanvas { +public int drawRenderNode(...); +public boolean isHardwareAccelerated(); +} +-keepclassmembers class androidx.compose.ui.graphics.layer.view.ViewLayerContainer { +protected void dispatchGetDisplayList(); +} +-keepclassmembers class androidx.compose.ui.platform.AndroidComposeView { +android.view.View findViewByAccessibilityIdTraversal(int); +} +-keepclassmembers class androidx.compose.ui.platform.ViewLayerContainer { +protected void dispatchGetDisplayList(); +} +-keepclassmembers class androidx.lifecycle.ReportFragment$LifecycleCallbacks { *; } +-keepclassmembers class androidx.transition.ChangeBounds$* extends android.animation.AnimatorListenerAdapter { +androidx.transition.ChangeBounds$ViewBounds mViewBounds; +} +-keepclassmembers class androidx.vectordrawable.graphics.drawable.VectorDrawableCompat$* { +void set*(***); +*** get*(); +} +-keepclassmembers class kotlin.coroutines.SafeContinuation { +volatile ; +} +-keepclassmembers class kotlinx.coroutines.** { +volatile ; +} +-keepclassmembers class soup.movie.** { +*** Companion; +} +-keepclassmembers enum * { +public static **[] values(); +public static ** valueOf(java.lang.String); +} +-keepclassmembers enum androidx.lifecycle.Lifecycle$Event { +; +} +-keepclassmembers public class * extends android.view.View { +void set*(***); +*** get*(); +} +-keepclassmembers public class * extends androidx.work.ListenableWorker { +public (...); +} +-keepclassmembers public class **$$serializer { +private ** descriptor; +} +-keepclassmembers,allowobfuscation class * extends androidx.lifecycle.AndroidViewModel { +(android.app.Application); +} +-keepclassmembers,allowobfuscation class * extends androidx.lifecycle.AndroidViewModel { +(android.app.Application,androidx.lifecycle.SavedStateHandle); +} +-keepclassmembers,allowobfuscation class * extends androidx.lifecycle.ViewModel { +(); +} +-keepclassmembers,allowobfuscation class * extends androidx.lifecycle.ViewModel { +(androidx.lifecycle.SavedStateHandle); +} +-keepclassmembers,allowobfuscation class * implements androidx.savedstate.SavedStateRegistry$AutoRecreated { +(); +} +-keepclassmembers,allowobfuscation class * { +@androidx.annotation.DoNotInline ; +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static java.lang.Void throw*Exception(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +static java.lang.String exceptionMessage*(...); +java.lang.String exceptionMessage*(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +} +-keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.runtime.** { +static void throw*Exception(...); +static void throw*ExceptionForNullCheck(...); +static java.lang.Void throw*Exception(...); +static java.lang.Void throw*ExceptionForNullCheck(...); +static java.lang.String exceptionMessage*(...); +java.lang.String exceptionMessage*(...); +static void compose*RuntimeError(...); +static java.lang.Void compose*RuntimeError(...); +} +-keepclassmembers,allowshrinking,allowobfuscation interface * { +@retrofit2.http.* ; +} +-keepnames @androidx.hilt.work.HiltWorker class * extends androidx.work.ListenableWorker +-keepnames @kotlinx.serialization.internal.NamedCompanion class * +-keepnames class * extends androidx.startup.Initializer +-keepnames class * extends androidx.work.InputMerger +-keepnames class * extends androidx.work.ListenableWorker +-keepnames class androidx.compose.ui.input.pointer.PointerInputEventHandler { +*; +} +-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase diff --git a/build.gradle b/build.gradle index 69fb5e90..554dfe9b 100644 --- a/build.gradle +++ b/build.gradle @@ -8,6 +8,7 @@ plugins { alias(libs.plugins.ksp) apply false alias(libs.plugins.dependencyGuard) apply false alias(libs.plugins.manifestShield) apply false + alias(libs.plugins.proguardShield) apply false alias(libs.plugins.baselineprofile) apply false } diff --git a/check.sh b/check.sh index 1dfd7294..9c6e7770 100755 --- a/check.sh +++ b/check.sh @@ -1,6 +1,6 @@ #!/bin/bash # Check script for PR submission -# Validates dependencies, merged manifest, code formatting, lint. +# Validates dependencies, merged manifest, ProGuard/R8 rules, code formatting, lint. # Exit immediately if any command fails set -e @@ -9,25 +9,31 @@ echo "Starting check validations..." echo "" # Verify dependency changes -echo "🔍 [1/4] Checking dependency guard..." +echo "🔍 [1/5] Checking dependency guard..." ./gradlew dependencyGuard echo "✓ Dependency guard check passed" echo "" # Verify merged manifest changes -echo "🔍 [2/4] Checking manifest shield..." +echo "🔍 [2/5] Checking manifest shield..." ./gradlew manifestShield echo "✓ Manifest shield check passed" echo "" +# Verify ProGuard/R8 rule changes +echo "🔍 [3/5] Checking proguard shield..." +./gradlew proguardShieldFast +echo "✓ ProGuard shield check passed" +echo "" + # Verify code formatting -echo "🔍 [3/4] Checking code formatting..." +echo "🔍 [4/5] Checking code formatting..." ./gradlew spotlessCheck --init-script gradle/init.gradle.kts echo "✓ Code formatting check passed" echo "" # Static analysis and lint checks -echo "🔍 [4/4] Running lint checks..." +echo "🔍 [5/5] Running lint checks..." ./gradlew lintDebug echo "✓ Lint check passed" echo "" diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 20b7ac4b..dc8b402f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -39,6 +39,7 @@ photo-compose = "1.0.1" coil = "3.3.0" dependencyGuard = "0.5.0" manifestShield = "0.1.10" +proguardShield = "0.0.3" retrofit = "3.0.0" timber = "5.0.1" @@ -151,4 +152,5 @@ compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = " ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } dependencyGuard = { id = "com.dropbox.dependency-guard", version.ref = "dependencyGuard" } manifestShield = { id = "io.github.fornewid.manifest-shield", version.ref = "manifestShield" } +proguardShield = { id = "io.github.fornewid.proguard-shield", version.ref = "proguardShield" } baselineprofile = { id = "androidx.baselineprofile", version.ref = "androidx-benchmark" } From 4c3ee9ef4a3f45cbf8ddb5e2400a88c7508cb865 Mon Sep 17 00:00:00 2001 From: "sungyong.an" Date: Sun, 27 Sep 2026 23:08:04 +0900 Subject: [PATCH 2/2] Keep only the fast proguard-shield baseline CI and check.sh run proguardShieldFast only, so drop the accurate releaseRules.txt baseline and re-baseline with proguardShieldFastBaseline, which doesn't run R8 or regenerate releaseRules.txt. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Upxj1FvQeDpycupKdPQHUZ --- CHECK.md | 2 +- app/proguardShield/releaseRules.txt | 451 ---------------------------- 2 files changed, 1 insertion(+), 452 deletions(-) delete mode 100644 app/proguardShield/releaseRules.txt diff --git a/CHECK.md b/CHECK.md index 083c4b6f..766a68e7 100644 --- a/CHECK.md +++ b/CHECK.md @@ -47,7 +47,7 @@ - proguardShield ```bash -./gradlew proguardShieldBaseline +./gradlew proguardShieldFastBaseline ``` - spotless diff --git a/app/proguardShield/releaseRules.txt b/app/proguardShield/releaseRules.txt deleted file mode 100644 index 6ecb65fa..00000000 --- a/app/proguardShield/releaseRules.txt +++ /dev/null @@ -1,451 +0,0 @@ --allowaccessmodification --assumenosideeffects class androidx.datastore.core.SharedCounter$Factory { -private boolean isDalvik() return true; -} --assumenosideeffects class androidx.startup.StartupLogger { public static ; } --assumenosideeffects class kotlinx.coroutines.DebugKt { -boolean getASSERTIONS_ENABLED() return false; -boolean getDEBUG() return false; -boolean getRECOVER_STACK_TRACES() return false; -} --assumenosideeffects class kotlinx.coroutines.internal.FastServiceLoaderKt { -boolean ANDROID_DETECTED return true; -} --assumenosideeffects class kotlinx.coroutines.internal.MainDispatcherLoader { -boolean FAST_SERVICE_LOADER_ENABLED return false; -} --assumenosideeffects class kotlinx.coroutines.internal.MainDispatchersKt { -boolean SUPPORT_MISSING return false; -} --assumenosideeffects public class androidx.compose.runtime.Composer { -void (); -} --assumenosideeffects public class androidx.compose.runtime.ComposerImpl { -void (); -} --assumenosideeffects public class androidx.compose.runtime.ComposerKt { -void sourceInformation(androidx.compose.runtime.Composer,java.lang.String); -void sourceInformationMarkerStart(androidx.compose.runtime.Composer,int,java.lang.String); -void sourceInformationMarkerEnd(androidx.compose.runtime.Composer); -} --assumevalues class androidx.compose.runtime.tooling.ComposeStackTraceMode { -private static boolean isMinified return true; -} --dontnote android.net.http.** --dontnote android.support.** --dontnote androidx.** --dontnote com.android.vending.licensing.ILicensingService --dontnote com.google.android.vending.licensing.ILicensingService --dontnote com.google.vending.licensing.ILicensingService --dontnote java.lang.invoke.** --dontnote kotlinx.serialization.** --dontnote kotlinx.serialization.SerializationKt --dontnote org.apache.http.** --dontwarn android.support.** --dontwarn android.support.** --dontwarn android.view.DisplayListCanvas --dontwarn android.view.HardwareCanvas --dontwarn android.view.RenderNode --dontwarn androidx.** --dontwarn androidx.** --dontwarn androidx.lifecycle.LiveData --dontwarn androidx.room.paging.** --dontwarn coil3.PlatformContext --dontwarn com.crashlytics.** --dontwarn com.google.errorprone.annotations.* --dontwarn java.lang.ClassValue --dontwarn java.lang.instrument.ClassFileTransformer --dontwarn java.lang.instrument.Instrumentation --dontwarn javax.annotation.** --dontwarn javax.annotation.** --dontwarn kotlin.Unit --dontwarn kotlinx.serialization.internal.ClassValueReferences --dontwarn okhttp3.internal.platform.** --dontwarn org.bouncycastle.** --dontwarn org.codehaus.mojo.animal_sniffer.* --dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement --dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement --dontwarn org.conscrypt.** --dontwarn org.jetbrains.annotations.** --dontwarn org.jetbrains.annotations.** --dontwarn org.openjsse.** --dontwarn retrofit2.KotlinExtensions --dontwarn retrofit2.KotlinExtensions$* --dontwarn soup.movie.log.Logger --dontwarn sun.misc.Signal --dontwarn sun.misc.SignalHandler --identifiernamestring @dagger.internal.IdentifierNameString class ** { -static java.lang.String *; -} --if @kotlinx.serialization.Serializable class ** --if @kotlinx.serialization.Serializable class ** --if @kotlinx.serialization.Serializable class ** { -public static ** INSTANCE; -} --if @kotlinx.serialization.Serializable class ** { -static **$* *; -} --if @kotlinx.serialization.internal.NamedCompanion class * --if class androidx.window.layout.adapter.sidecar.SidecarCompat { -public *** setExtensionCallback(androidx.window.layout.adapter.sidecar.ExtensionInterfaceCompat$ExtensionCallbackInterface); -} --if interface * { @retrofit2.http.* ; } --if interface * { @retrofit2.http.* ; } --if interface * { @retrofit2.http.* public *** *(...); } --if public class ** extends androidx.fragment.app.Fragment --if public class androidx.compose.ui.platform.AndroidCompositionLocals_androidKt { -public static *** getLocalLifecycleOwner(); -} --if public class androidx.compose.ui.platform.AndroidCompositionLocals_androidKt { -public static *** getLocalSavedStateRegistryOwner(); -} --keep @android.support.annotation.Keep class * {*;} --keep @androidx.annotation.Keep class * {*;} --keep class * extends androidx.room.RoomDatabase { void (); } --keep class * extends androidx.startup.Initializer { -(); -} --keep class * implements androidx.lifecycle.GeneratedAdapter { -(...); -} --keep class * implements androidx.versionedparcelable.VersionedParcelable --keep class android.support.annotation.Keep --keep class android.widget.Space { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.app.AlertController$RecycleListView { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.view.menu.ActionMenuItemView { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.view.menu.ExpandedMenuView { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.view.menu.ListMenuItemView { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.widget.ActionBarContainer { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.widget.ActionBarContextView { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.widget.ActionBarOverlayLayout { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.widget.ActionMenuView { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.widget.ActivityChooserView$InnerLayout { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.widget.AlertDialogLayout { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.widget.ButtonBarLayout { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.widget.ContentFrameLayout { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.widget.DialogTitle { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.widget.FitWindowsFrameLayout { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.widget.FitWindowsLinearLayout { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.widget.SearchView$SearchAutoComplete { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.widget.Toolbar { (android.content.Context, android.util.AttributeSet); } --keep class androidx.appcompat.widget.ViewStubCompat { (android.content.Context, android.util.AttributeSet); } --keep class androidx.browser.browseractions.BrowserActionsFallbackMenuView { (android.content.Context, android.util.AttributeSet); } --keep class androidx.core.app.CoreComponentFactory { (); } --keep class androidx.core.widget.NestedScrollView { (android.content.Context, android.util.AttributeSet); } --keep class androidx.profileinstaller.ProfileInstallReceiver { (); } --keep class androidx.room.MultiInstanceInvalidationService { (); } --keep class androidx.startup.InitializationProvider { (); } --keep class androidx.window.layout.adapter.sidecar.SidecarCompat$TranslatingCallback, -androidx.window.layout.adapter.sidecar.DistinctElementSidecarCallback { -public *** onDeviceStateChanged(androidx.window.sidecar.SidecarDeviceState); -public *** onWindowLayoutChanged(android.os.IBinder, androidx.window.sidecar.SidecarWindowLayoutInfo); -} --keep class androidx.work.WorkerParameters --keep class androidx.work.impl.background.systemalarm.RescheduleReceiver { (); } --keep class androidx.work.impl.background.systemjob.SystemJobService { (); } --keep class androidx.work.impl.diagnostics.DiagnosticsReceiver { (); } --keep class androidx.work.impl.foreground.SystemForegroundService { (); } --keep class androidx.work.impl.utils.ForceStopRunnable$BroadcastReceiver { (); } --keep class com.crashlytics.** { *; } --keep class kotlin.Metadata { *; } --keep class soup.movie.MovieApplication { (); } --keep class soup.movie.data.database.internal.entity.** { *; } --keep class soup.movie.data.network.response.** { *; } --keep class soup.movie.ui.main.MainActivity { (); } --keep interface androidx.window.area.reflectionguard.* {*;} --keep interface androidx.window.reflection.Consumer2 { -public *** accept(***); -} --keep interface androidx.window.reflection.JFunction2 { -public *** apply(***); -} --keep interface androidx.window.reflection.Predicate2 { -public *** test(***); -} --keep public class android.support.**Parcelizer { *; } --keep public class androidx.**Parcelizer { *; } --keep public class androidx.compose.ui.platform.AndroidCompositionLocals_androidKt { -public static *** getLocalLifecycleOwner(); -} --keep public class androidx.compose.ui.platform.AndroidCompositionLocals_androidKt { -public static *** getLocalSavedStateRegistryOwner(); -} --keep public class androidx.versionedparcelable.ParcelImpl --keep public class com.android.vending.licensing.ILicensingService --keep public class com.google.android.vending.licensing.ILicensingService --keep public class com.google.vending.licensing.ILicensingService --keep, allowshrinking, allowoptimization, allowobfuscation, allowaccessmodification class <1> --keep,allowobfuscation @interface androidx.annotation.Keep --keep,allowobfuscation interface * extends <1> --keep,allowobfuscation interface <1> --keep,allowobfuscation,allowshrinking @dagger.hilt.EntryPoint class * --keep,allowobfuscation,allowshrinking @dagger.hilt.android.EarlyEntryPoint class * --keep,allowobfuscation,allowshrinking @dagger.hilt.internal.ComponentEntryPoint class * --keep,allowobfuscation,allowshrinking @dagger.hilt.internal.GeneratedEntryPoint class * --keep,allowobfuscation,allowshrinking class * extends androidx.compose.ui.node.ModifierNodeElement --keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation --keep,allowobfuscation,allowshrinking class retrofit2.Response --keep,allowobfuscation,allowshrinking class soup.movie.feature.detail.impl.DetailViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.detail.impl.DetailViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.HomeViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.HomeViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.favorite.HomeFavoriteViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.favorite.HomeFavoriteViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.filter.HomeFilterViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.filter.HomeFilterViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.now.HomeNowViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.now.HomeNowViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.plan.HomePlanViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.home.impl.plan.HomePlanViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.search.impl.SearchViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.search.impl.SearchViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.settings.impl.home.SettingsViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.settings.impl.home.SettingsViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.settings.impl.theme.ThemeOptionViewModel --keep,allowobfuscation,allowshrinking class soup.movie.feature.settings.impl.theme.ThemeOptionViewModel --keep,allowobfuscation,allowshrinking class soup.movie.ui.main.MainViewModel --keep,allowobfuscation,allowshrinking class soup.movie.ui.main.MainViewModel --keep,allowoptimization,allowshrinking,allowobfuscation class <3> --keep,allowshrinking class androidx.window.layout.adapter.extensions.MulticastConsumer { -void accept(androidx.window.extensions.layout.WindowLayoutInfo); -} --keep,includedescriptorclasses class soup.movie.**$$serializer { *; } --keepattributes *Annotation*, InnerClasses --keepattributes AnnotationDefault --keepattributes AnnotationDefault, -EnclosingMethod, -InnerClasses, -RuntimeVisibleAnnotations, -RuntimeVisibleParameterAnnotations, -RuntimeVisibleTypeAnnotations, -Signature --keepattributes AnnotationDefault, -RuntimeVisibleAnnotations, -RuntimeVisibleParameterAnnotations, -RuntimeVisibleTypeAnnotations --keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations --keepattributes RuntimeVisibleAnnotations,AnnotationDefault --keepattributes Signature, InnerClasses, EnclosingMethod --keepclasseswithmembernames,includedescriptorclasses class * { -native ; -} --keepclasseswithmembernames,includedescriptorclasses class androidx.datastore.core.NativeSharedCounter { -native ; -} --keepclasseswithmembers class * { -@android.support.annotation.Keep ; -} --keepclasseswithmembers class * { -@android.support.annotation.Keep (...); -} --keepclasseswithmembers class * { -@android.support.annotation.Keep ; -} --keepclasseswithmembers class * { -@androidx.annotation.Keep ; -} --keepclasseswithmembers class * { -@androidx.annotation.Keep (...); -} --keepclasseswithmembers class * { -@androidx.annotation.Keep ; -} --keepclasseswithmembers class androidx.graphics.path.** { -native ; -} --keepclasseswithmembers class soup.movie.** { -kotlinx.serialization.KSerializer serializer(...); -} --keepclasseswithmembers,allowobfuscation public class <1> { -public (); -} --keepclasseswithmembers,allowobfuscation public class androidx.lifecycle.ReportFragment { -public (); -} --keepclassmembernames class * { -static <1> *; -} --keepclassmembernames,allowobfuscation,allowshrinking class androidx.appcompat.widget.AppCompatTextViewAutoSizeHelper$Impl* { -; -} --keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.app.NotificationCompat$*$Api*Impl { -; -} --keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.os.UserHandleCompat$Api*Impl { -; -} --keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.view.ViewCompat$Api* { -; -} --keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.view.WindowInsetsCompat$*Impl* { -; -} --keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.widget.EdgeEffectCompat$Api*Impl { -; -} --keepclassmembers @kotlinx.serialization.Serializable class ** { -public static ** INSTANCE; -kotlinx.serialization.KSerializer serializer(...); -} --keepclassmembers class * extends android.app.Activity { -public void *(android.view.View); -} --keepclassmembers class * extends androidx.datastore.preferences.protobuf.GeneratedMessageLite { -; -} --keepclassmembers class * extends androidx.lifecycle.EmptyActivityLifecycleCallbacks { *; } --keepclassmembers class * extends androidx.work.InputMerger { void (); } --keepclassmembers class * implements android.os.Parcelable { -public static final ** CREATOR; -} --keepclassmembers class * { -@android.webkit.JavascriptInterface ; -} --keepclassmembers class ** { -@androidx.lifecycle.OnLifecycleEvent *; -} --keepclassmembers class <1> { -public static <1> INSTANCE; -kotlinx.serialization.KSerializer serializer(...); -} --keepclassmembers class <1> { -static <1>$* Companion; -} --keepclassmembers class <2>$<3> { -kotlinx.serialization.KSerializer serializer(...); -} --keepclassmembers class androidx.compose.ui.graphics.layer.view.PlaceholderHardwareCanvas { -public int drawRenderNode(...); -public boolean isHardwareAccelerated(); -} --keepclassmembers class androidx.compose.ui.graphics.layer.view.ViewLayerContainer { -protected void dispatchGetDisplayList(); -} --keepclassmembers class androidx.compose.ui.platform.AndroidComposeView { -android.view.View findViewByAccessibilityIdTraversal(int); -} --keepclassmembers class androidx.compose.ui.platform.ViewLayerContainer { -protected void dispatchGetDisplayList(); -} --keepclassmembers class androidx.lifecycle.ReportFragment$LifecycleCallbacks { *; } --keepclassmembers class androidx.transition.ChangeBounds$* extends android.animation.AnimatorListenerAdapter { -androidx.transition.ChangeBounds$ViewBounds mViewBounds; -} --keepclassmembers class androidx.vectordrawable.graphics.drawable.VectorDrawableCompat$* { -void set*(***); -*** get*(); -} --keepclassmembers class kotlin.coroutines.SafeContinuation { -volatile ; -} --keepclassmembers class kotlinx.coroutines.** { -volatile ; -} --keepclassmembers class soup.movie.** { -*** Companion; -} --keepclassmembers enum * { -public static **[] values(); -public static ** valueOf(java.lang.String); -} --keepclassmembers enum androidx.lifecycle.Lifecycle$Event { -; -} --keepclassmembers public class * extends android.view.View { -void set*(***); -*** get*(); -} --keepclassmembers public class * extends androidx.work.ListenableWorker { -public (...); -} --keepclassmembers public class **$$serializer { -private ** descriptor; -} --keepclassmembers,allowobfuscation class * extends androidx.lifecycle.AndroidViewModel { -(android.app.Application); -} --keepclassmembers,allowobfuscation class * extends androidx.lifecycle.AndroidViewModel { -(android.app.Application,androidx.lifecycle.SavedStateHandle); -} --keepclassmembers,allowobfuscation class * extends androidx.lifecycle.ViewModel { -(); -} --keepclassmembers,allowobfuscation class * extends androidx.lifecycle.ViewModel { -(androidx.lifecycle.SavedStateHandle); -} --keepclassmembers,allowobfuscation class * implements androidx.savedstate.SavedStateRegistry$AutoRecreated { -(); -} --keepclassmembers,allowobfuscation class * { -@androidx.annotation.DoNotInline ; -} --keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { -static void throw*Exception(...); -static java.lang.Void throw*Exception(...); -} --keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { -static void throw*Exception(...); -static void throw*ExceptionForNullCheck(...); -static java.lang.Void throw*Exception(...); -static java.lang.Void throw*ExceptionForNullCheck(...); -static java.lang.String exceptionMessage*(...); -java.lang.String exceptionMessage*(...); -} --keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { -static void throw*Exception(...); -static void throw*ExceptionForNullCheck(...); -static java.lang.Void throw*Exception(...); -static java.lang.Void throw*ExceptionForNullCheck(...); -} --keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { -static void throw*Exception(...); -static void throw*ExceptionForNullCheck(...); -static java.lang.Void throw*Exception(...); -static java.lang.Void throw*ExceptionForNullCheck(...); -} --keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { -static void throw*Exception(...); -static void throw*ExceptionForNullCheck(...); -static java.lang.Void throw*Exception(...); -static java.lang.Void throw*ExceptionForNullCheck(...); -} --keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { -static void throw*Exception(...); -static void throw*ExceptionForNullCheck(...); -static java.lang.Void throw*Exception(...); -static java.lang.Void throw*ExceptionForNullCheck(...); -} --keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { -static void throw*Exception(...); -static void throw*ExceptionForNullCheck(...); -static java.lang.Void throw*Exception(...); -static java.lang.Void throw*ExceptionForNullCheck(...); -} --keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.**.* { -static void throw*Exception(...); -static void throw*ExceptionForNullCheck(...); -static java.lang.Void throw*Exception(...); -static java.lang.Void throw*ExceptionForNullCheck(...); -} --keepclassmembers,allowshrinking,allowobfuscation class androidx.compose.runtime.** { -static void throw*Exception(...); -static void throw*ExceptionForNullCheck(...); -static java.lang.Void throw*Exception(...); -static java.lang.Void throw*ExceptionForNullCheck(...); -static java.lang.String exceptionMessage*(...); -java.lang.String exceptionMessage*(...); -static void compose*RuntimeError(...); -static java.lang.Void compose*RuntimeError(...); -} --keepclassmembers,allowshrinking,allowobfuscation interface * { -@retrofit2.http.* ; -} --keepnames @androidx.hilt.work.HiltWorker class * extends androidx.work.ListenableWorker --keepnames @kotlinx.serialization.internal.NamedCompanion class * --keepnames class * extends androidx.startup.Initializer --keepnames class * extends androidx.work.InputMerger --keepnames class * extends androidx.work.ListenableWorker --keepnames class androidx.compose.ui.input.pointer.PointerInputEventHandler { -*; -} --keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase