diff --git a/OneSignalSDK/onesignal/core/consumer-rules.pro b/OneSignalSDK/onesignal/core/consumer-rules.pro index ccca56308..3b36daf97 100644 --- a/OneSignalSDK/onesignal/core/consumer-rules.pro +++ b/OneSignalSDK/onesignal/core/consumer-rules.pro @@ -1,19 +1,39 @@ --dontwarn com.onesignal.** - +# Amazon ADM is a compileOnly dependency; suppress missing-class warnings when the app omits it. -dontwarn com.amazon.** --keepclassmembers class com.onesignal.core.** { *; } - --keepclassmembers class com.onesignal.session.** { *; } - --keepclassmembers class com.onesignal.user.** { *; } - --keepclassmembers class com.onesignal.internal.** { *; } - --keepclassmembers class com.onesignal.debug.** { *; } - --keepclassmembers class com.onesignal.common.** { *; } - +# ServiceRegistrationReflection.resolve matches constructors via genericParameterTypes +# (e.g. List). Keep Signature so R8 cannot strip that metadata. +-keepattributes Signature + +# Service implementations are instantiated by reflectively selecting a constructor +# (ServiceRegistrationReflection.resolve -> constructor.newInstance). The classes are retained via +# ::class.java literals in the modules, so only their constructors need protecting here. +-keepclassmembers class com.onesignal.** { + (...); +} + +# Models are populated from JSON by matching getter method *names* via reflection +# (Model.initializeFromJson looks up "get"). Kotlin boolean properties also expose +# is*() getters that must keep their names. No allowobfuscation. +-keepclassmembers class * extends com.onesignal.common.modeling.Model { + *** get*(); + *** is*(); +} + +# Enum constants are looked up by name via valueOf/enumValueOf against server-supplied strings +# (e.g. Model.getOptEnumProperty -> ConfigModel.logLevel from remote-params JSON). Their names must +# survive obfuscation, so keep enum fields and the synthetic values()/valueOf(String) methods. +-keepclassmembers enum com.onesignal.** { + ; + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +# Optional feature modules are loaded by fully-qualified name (OneSignalImp loads them via +# Class.forName(...).newInstance()), so the name must be preserved and a no-arg constructor kept. +-keep class ** implements com.onesignal.common.modules.IModule { + (); +} + +# Fallback "misconfigured" managers are reflectively constructed when an optional module is absent. -keepclassmembers @com.onesignal.core.internal.minification.KeepStub class * { (...); } - --keep class ** implements com.onesignal.common.modules.IModule { *; } diff --git a/OneSignalSDK/onesignal/in-app-messages/consumer-rules.pro b/OneSignalSDK/onesignal/in-app-messages/consumer-rules.pro index 644bfe12f..165ed4507 100644 --- a/OneSignalSDK/onesignal/in-app-messages/consumer-rules.pro +++ b/OneSignalSDK/onesignal/in-app-messages/consumer-rules.pro @@ -1,3 +1,13 @@ --dontwarn com.onesignal.iam.** +# In-app-messages service implementations are instantiated via reflective constructor selection +# (ServiceRegistrationReflection). Keep only their constructors. +-keepclassmembers class com.onesignal.inAppMessages.** { + (...); +} --keepclassmembers class com.onesignal.inAppMessages.** { *; } \ No newline at end of file +# IAM display Position is resolved via Position.valueOf(serverString) (WebViewManager) and the +# IllegalArgumentException on a renamed constant is uncaught. Keep enum constant names. +-keepclassmembers enum com.onesignal.inAppMessages.** { + ; + public static **[] values(); + public static ** valueOf(java.lang.String); +} diff --git a/OneSignalSDK/onesignal/location/consumer-rules.pro b/OneSignalSDK/onesignal/location/consumer-rules.pro index 40ec90dc9..3bfba8a43 100644 --- a/OneSignalSDK/onesignal/location/consumer-rules.pro +++ b/OneSignalSDK/onesignal/location/consumer-rules.pro @@ -1,3 +1,19 @@ --dontwarn com.onesignal.location.** +# Location service implementations are instantiated via reflective constructor selection +# (ServiceRegistrationReflection). Keep only their constructors. +-keepclassmembers class com.onesignal.location.** { + (...); +} --keepclassmembers class com.onesignal.location.** { *; } \ No newline at end of file +# GMS and HMS location libraries are compileOnly; LocationModule references both +# GmsLocationController and HmsLocationController directly, so an app that ships only one +# provider will see the other's classes as missing at R8 time. +-dontwarn com.google.android.gms.** +-dontwarn com.huawei.** + +# GoogleApiClientCompatProxy invokes these GMS methods reflectively by string name (for +# compatibility across Google Play services versions), so their names must be preserved. +-keepclassmembers class com.google.android.gms.common.api.GoogleApiClient { + com.google.android.gms.common.ConnectionResult blockingConnect(); + void connect(); + void disconnect(); +} diff --git a/OneSignalSDK/onesignal/notifications/consumer-rules.pro b/OneSignalSDK/onesignal/notifications/consumer-rules.pro index c348aaaa1..4eb5e15f6 100644 --- a/OneSignalSDK/onesignal/notifications/consumer-rules.pro +++ b/OneSignalSDK/onesignal/notifications/consumer-rules.pro @@ -1,62 +1,43 @@ --dontwarn com.onesignal.notification.** - -# These 2 methods are called with reflection. --keep class com.google.android.gms.common.api.GoogleApiClient { - void connect(); - void disconnect(); -} - -# Need to keep as these 2 methods are called with reflection from com.onesignal.PushRegistratorFCM --keep class com.google.firebase.iid.FirebaseInstanceId { - static com.google.firebase.iid.FirebaseInstanceId getInstance(com.google.firebase.FirebaseApp); - java.lang.String getToken(java.lang.String, java.lang.String); -} - --keep class ** implements com.onesignal.notifications.IPermissionObserver{ - void onNotificationPermissionChange(java.lang.Boolean); -} - --keep class ** implements com.onesignal.user.subscriptions.IPushSubscriptionObserver { - void onPushSubscriptionChange(com.onesignal.user.subscriptions.PushSubscriptionChangedState); -} - --keep class ** implements com.onesignal.user.state.IUserStateObserver { - void onUserStateChange(com.onesignal.user.state.UserChangedState); -} - --keep class ** implements com.onesignal.notifications.INotificationServiceExtension{ +# The notification service extension class is named in the app's AndroidManifest and is +# reflectively instantiated (NotificationLifecycleService -> Class.forName(name).newInstance()), so the +# class name and its no-arg constructor must be preserved. +-keep class ** implements com.onesignal.notifications.INotificationServiceExtension { + (); void onNotificationReceived(com.onesignal.notifications.INotificationReceivedEvent); } --keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.AdwHomeBadger { (...); } --keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.ApexHomeBadger { (...); } --keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.AsusHomeBadger { (...); } --keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.DefaultBadger { (...); } --keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.EverythingMeHomeBadger { (...); } --keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.HuaweiHomeBadger { (...); } --keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.LGHomeBadger { (...); } --keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.NewHtcHomeBadger { (...); } --keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.NovaHomeBadger { (...); } --keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.OPPOHomeBader { (...); } --keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.SamsungHomeBadger { (...); } --keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.SonyHomeBadger { (...); } --keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.VivoHomeBadger { (...); } --keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.XiaomiHomeBadger { (...); } --keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.ZukHomeBadger { (...); } +# Home-screen badgers are instantiated via newInstance() from a list of class literals +# (ShortcutBadger.initBadger), so each implementation needs its constructor kept. +-keep class * implements com.onesignal.notifications.internal.badges.impl.shortcutbadger.Badger { + (...); +} +# Optional / excludable push providers are referenced directly by the provider-specific +# registrators. firebase-messaging is api (pulled in by default) but Huawei apps routinely +# exclude it; play-services-base, HMS, and ADM are compileOnly. When a consuming app omits a +# provider, those classes are absent at R8 time: Huawei-only apps drop firebase-messaging (and +# typically have no Play services), so PushRegistratorFCM's com.google.firebase.** / +# com.google.android.gms.tasks.** and GooglePlayServicesUpgradePrompt's +# com.google.android.gms.common.** are missing; GMS apps omit HMS (com.huawei.**) and ADM +# (com.amazon.**). Suppress the missing-class errors for all of them. -dontwarn com.huawei.** -dontwarn com.amazon.** +-dontwarn com.google.firebase.** +-dontwarn com.google.android.gms.** -# Proguard ends up removing this class even if it is used in AndroidManifest.xml so force keeping it. --keep public class com.onesignal.notifications.services.ADMMessageHandler {*;} +# ADM handlers are instantiated by name from the app manifest AND their on* lifecycle callbacks +# (onMessage/onRegistered/onRegistrationError/onUnregistered) are invoked by the ADM framework, not +# the SDK, so keep both constructors and those methods. (Amazon-device-only path, untestable in CI.) +-keep public class com.onesignal.notifications.services.ADMMessageHandler { (...); void on*(...); } +-keep public class com.onesignal.notifications.services.ADMMessageHandlerJob { (...); void on*(...); } --keep public class com.onesignal.notifications.services.ADMMessageHandlerJob {*;} - --keep class com.onesignal.JobIntentService$* {*;} - --keepclassmembers class com.onesignal.notifications.** { *; } +# Notification service implementations are instantiated via reflective constructor selection +# (ServiceRegistrationReflection). Keep only their constructors. +-keepclassmembers class com.onesignal.notifications.** { + (...); +} -# Keep OneSignal WorkManager workers and constructors used for runtime instantiation. +# WorkManager instantiates workers via reflection using the (Context, WorkerParameters) constructor. -keep class com.onesignal.notifications.internal.** extends androidx.work.ListenableWorker { public (android.content.Context, androidx.work.WorkerParameters); } @@ -64,9 +45,7 @@ # WorkManager instantiates InputMerger classes via reflection (InputMerger.fromClassName). # R8 full mode (AGP 8+) strips no-arg constructors, causing: # java.lang.NoSuchMethodException: androidx.work.OverwritingInputMerger.() -# WM-WorkerWrapper E Could not create Input Merger androidx.work.OverwritingInputMerger # Keep all InputMerger subclasses (OverwritingInputMerger, ArrayCreatingInputMerger, etc.) -keep class * extends androidx.work.InputMerger { public (); } - diff --git a/examples/demo/app/build.gradle.kts b/examples/demo/app/build.gradle.kts index f28cae61a..2d233dcf5 100644 --- a/examples/demo/app/build.gradle.kts +++ b/examples/demo/app/build.gradle.kts @@ -98,7 +98,7 @@ android { signingConfig = signingConfigs.getByName("debug") proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" + "proguard-rules.pro", ) } debug {