Open IainS1986 opened 10 months ago
Ok, this is an R8 shrinker issue.
I've tried adding some custom proguard rules but I'm struggling to get it to work.
-keep public class com.onesignal.* {;} -keep interface com.onesignal.* {;}
Works to get past the basic method missing errors but then I get the following Java.Lang.Exception...
Service interface com.onesignal.core.internal.operations.IOperationRepo could not be instantiated
I thought the keep interface line above would resolve this but it didn't. Any ideas what rules are needed?
Does anyone have working, R8 shrinker rules for OneSignal on Android?
I've tried using older proguard rules from here https://github.com/OneSignal/OneSignal-Android-SDK/blob/main/OneSignalSDK/onesignal/consumer-proguard-rules.pro#L51 but this isn't working with R8 shrinking.
Turning off R8 works fine, I'm sure our older Xamarin native project using OneSignal was R8 shrinking so this seems a specific problem in the new .net-android SDK support.
Can't seem to get the R8 not to break whatever it is that implements IOperationRepo
[mono-rt] java.lang.Exception: Service interface com.onesignal.core.internal.operations.IOperationRepo could not be instantiated
[mono-rt] at com.onesignal.common.services.ServiceProvider.getService(ServiceProvider.kt:70)
[mono-rt] at com.onesignal.internal.OneSignalImp.initWithContext(OneSignalImp.kt:40)
[mono-rt] at com.onesignal.OneSignal.initWithContext(OneSignal.kt:126)
Is there anyone from OneSignal able to advise on how to use this SDK with R8 shrinking on Android?
This is the Full Proguard rules i've tried for OneSignal (based off the old Xamarin one and the Android project) but not had any success yet...
# OneSignal
# https://github.com/OneSignal/OneSignal-Android-SDK/blob/main/OneSignalSDK/onesignal/consumer-proguard-rules.pro#L51
-dontwarn com.amazon.**
-dontwarn com.google.android.gms.location.LocationListener
-dontwarn com.onesignal.**
-dontwarn com.onesignal.notification.**
-keep class com.google.firebase.provider.** { *; }
-keep class com.onesignal.** { *; }
-keep interface com.onesignal.** { *; }
-keep class com.onesignal.ActivityLifecycleListenerCompat** {*;}
# 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.notifications.INotificationServiceExtension{
void onNotificationReceived(com.onesignal.notifications.INotificationReceivedEvent);
}
# Observer backcall methods are called with reflection
-keep class com.onesignal.OSSubscriptionState {
void changed(com.onesignal.OSPermissionState);
}
-keep class com.onesignal.OSPermissionChangedInternalObserver {
void changed(com.onesignal.OSPermissionState);
}
-keep class com.onesignal.OSSubscriptionChangedInternalObserver {
void changed(com.onesignal.OSSubscriptionState);
}
-keep class com.onesignal.OSEmailSubscriptionChangedInternalObserver {
void changed(com.onesignal.OSEmailSubscriptionState);
}
-keep class com.onesignal.OSSMSSubscriptionChangedInternalObserver {
void changed(com.onesignal.OSSMSSubscriptionState);
}
-keep class ** implements com.onesignal.OSPermissionObserver {
void onOSPermissionChanged(com.onesignal.OSPermissionStateChanges);
}
-keep class ** implements com.onesignal.OSSubscriptionObserver {
void onOSSubscriptionChanged(com.onesignal.OSSubscriptionStateChanges);
}
-keep class ** implements com.onesignal.OSEmailSubscriptionObserver {
void onOSEmailSubscriptionChanged(com.onesignal.OSEmailSubscriptionStateChanges);
}
-keep class ** implements com.onesignal.OSSMSSubscriptionObserver {
void onOSEmailSubscriptionChanged(com.onesignal.OSSMSSubscriptionStateChanges);
}
-keep class com.onesignal.shortcutbadger.impl.AdwHomeBadger { <init>(...); }
-keep class com.onesignal.shortcutbadger.impl.ApexHomeBadger { <init>(...); }
-keep class com.onesignal.shortcutbadger.impl.AsusHomeBadger { <init>(...); }
-keep class com.onesignal.shortcutbadger.impl.DefaultBadger { <init>(...); }
-keep class com.onesignal.shortcutbadger.impl.EverythingMeHomeBadger { <init>(...); }
-keep class com.onesignal.shortcutbadger.impl.HuaweiHomeBadger { <init>(...); }
-keep class com.onesignal.shortcutbadger.impl.LGHomeBadger { <init>(...); }
-keep class com.onesignal.shortcutbadger.impl.NewHtcHomeBadger { <init>(...); }
-keep class com.onesignal.shortcutbadger.impl.NovaHomeBadger { <init>(...); }
-keep class com.onesignal.shortcutbadger.impl.OPPOHomeBader { <init>(...); }
-keep class com.onesignal.shortcutbadger.impl.SamsungHomeBadger { <init>(...); }
-keep class com.onesignal.shortcutbadger.impl.SonyHomeBadger { <init>(...); }
-keep class com.onesignal.shortcutbadger.impl.VivoHomeBadger { <init>(...); }
-keep class com.onesignal.shortcutbadger.impl.XiaomiHomeBadger { <init>(...); }
-keep class com.onesignal.shortcutbadger.impl.ZukHomeBadger { <init>(...); }
-keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.AdwHomeBadger { <init>(...); }
-keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.ApexHomeBadger { <init>(...); }
-keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.AsusHomeBadger { <init>(...); }
-keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.DefaultBadger { <init>(...); }
-keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.EverythingMeHomeBadger { <init>(...); }
-keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.HuaweiHomeBadger { <init>(...); }
-keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.LGHomeBadger { <init>(...); }
-keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.NewHtcHomeBadger { <init>(...); }
-keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.NovaHomeBadger { <init>(...); }
-keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.OPPOHomeBader { <init>(...); }
-keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.SamsungHomeBadger { <init>(...); }
-keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.SonyHomeBadger { <init>(...); }
-keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.VivoHomeBadger { <init>(...); }
-keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.XiaomiHomeBadger { <init>(...); }
-keep class com.onesignal.notifications.internal.badges.impl.shortcutbadger.impl.ZukHomeBadger { <init>(...); }
-dontwarn com.amazon.**
-dontwarn com.huawei.**
# Proguard ends up removing this class even if it is used in AndroidManifest.xml so force keeping it.
-keep public class com.onesignal.ADMMessageHandler {*;}
-keep public class com.onesignal.ADMMessageHandlerJob {*;}
# OSRemoteNotificationReceivedHandler is an interface designed to be extend then referenced in the
# app's AndroidManifest.xml as a meta-data tag.
# This doesn't count as a hard reference so this entry is required.
-keep class ** implements com.onesignal.OneSignal$OSRemoteNotificationReceivedHandler {
void remoteNotificationReceived(android.content.Context, com.onesignal.OSNotificationReceivedEvent);
}
-keep class com.onesignal.JobIntentService$* {*;}
-keep class com.onesignal.OneSignalUnityProxy {*;}
-keepclassmembers class com.onesignal.notifications.** { *; }
Example Repo of the issue (using MAUI)
https://github.com/IainS1986/OneSignal-R8-Test
This is a basic MAUI template (from Rider).
When I run a release configuration build to my phone I get the same exception…
FATAL EXCEPTION: main Process: com.companyname.mauiapp1, PID: 1221 java.lang.RuntimeException: Unable to create application crc64e632a077a20c694c.MainApplication: java.lang.Exception: Service interface com.onesignal.core.internal.operations.IOperationRepo could not be instantiated
Same problema here...
I had to add this instruction to my Proguard file to fix it: -keepattributes Signature
When I try adding that I'm getting a whole bunch of R8 errors "A type or variable is not in scope."
Can you share your whole proguard file?
-dontwarn com.onesignal.**
-keep class com.google.android.gms.common.api.GoogleApiClient { void connect(); void disconnect(); }
-keep class com.onesignal.* {;} -keepattributes Signature
-keepclassmembers class { @android.webkit.JavascriptInterface ; }
It seems only this was enough for my project. At least for initializing the onesignal.
Cheers, mayhbe theres something else in my proguard colliding with this, i'll try removing bits and adding bits and see how I go, cheers for pointing this line out though 👍
My project is Xamarin and it's using the version 5.0.2.
Might be the difference too, this is specifically about .net-android 8+ (which you'll have to port over too soon). Hard to tell thought 🤷
I don't think it doesn't change much because it's using the onesignal android 5.0.3. It should be the same.
Proguard effects your entire app. Not just onesignal. So it might fix it, but adding that line breaks some other sections in my proguard that (may) be needed for .net-android, I can't say for sure so will need some time to go through things bit by bit. I think it broke an AndroidX section in my proguard but will see.
# OneSignal
# https://github.com/OneSignal/OneSignal-Android-SDK/blob/main/OneSignalSDK/onesignal/consumer-proguard-rules.pro#L51
-dontwarn com.onesignal.**
-keep class com.microsoft.maui.** {*;}
-keep class androidx.startup.** {*;}
-dontwarn com.amazon.**
-dontwarn com.google.firebase.**
-keep class com.google.firebase.**
# OneSignal - Proguard ends up removing this class even if it is used in AndroidManifest.xml so force keeping it.
-keep class com.onesignal.** {*;}
-keepattributes Signature
# Keep methods annotated with @JavascriptInterface for webview bridge (InApp feature)
-keepclassmembers class * {
@android.webkit.JavascriptInterface *;
}
# End OneSignal
I tried to change your maui test app using this configuration.
When I'm refering the my proguard file thats breaking I'm not referring to that test project, that was for the OneSignal team to investigate.
The proguard file I have in another app is much larger. But I'll dig more into it but won't be happening for a week or two
I narrowed it down to the following lines that break with the keepattributes Signature line,
-dontwarn androidx.**
-keep class androidx.** { *; }
-keep interface androidx.** { *; }
So I need to figure out the exact bits of AndroidX to keep as opposed to an (ugly) blanket keep on the whole thing
Ok. After a lot of head banging I think I've resolved the issue.
So as @arctouch-rafaelpontes above pointed out, you do need to have this in your proguard,
-keepattributes Signature
But, you might (like me) have the following your proguard
-keep class androidx.** { *; }
These two lines do not work together. Ideally, you shouldn't be just having keep on the whole androidx, but its a faff not doing that if you need it. However you'll need to work out all references you are using in androidx and only include those. This is not fun.
Thankfully, someone did a lot of leg work already around this issue they were having with a different library here https://github.com/xamarin/xamarin-android/issues/7008
So from this, I managed to make the following proguard that works, you might have some things still fail that you need to add, but this should work.
# OneSignal
-keep class com.onesignal.** { *; }
-keep class com.onesignal.core.** { *; }
-keep class com.onesignal.session.** { *; }
-keep class com.onesignal.user.** { *; }
-keep class com.onesignal.internal.** { *; }
-keep class com.onesignal.debug.** { *; }
-keep class com.onesignal.common.** { *; }
-keep class ** implements com.onesignal.common.modules.IModule { *; }
# https://github.com/xamarin/xamarin-android/issues/7008#issuecomment-1789672213
-keepattributes AnnotationDefault,
EnclosingMethod,
InnerClasses,
RuntimeVisibleAnnotations, # <-- Kotlin metadata is a runtime-visible annotation
RuntimeVisibleParameterAnnotations,
RuntimeVisibleTypeAnnotations,
Signature
# Glide and MAUI Essentials
-keep class com.microsoft.maui.** { *; }
-keep class com.bumptech.glide.** { *; }
# Google Android Material
-keep class com.google.android.material.** { *; }
# AndroidX
-keep class androidx.activity.result.** { *; }
-keep class androidx.appcompat.** { *; }
-keep class androidx.autofill.** { *; }
-keep class androidx.biometric.** { *; }
-keep class androidx.core.app.** { *; }
-keep class androidx.core.content.pm.PackageInfoCompat { *; }
-keep class androidx.core.net.** { *; }
-keep class androidx.core.splashscreen.SplashScreen { *; }
-keep class androidx.core.text.** { *; }
-keep class androidx.core.transition.** { *; }
-keep class androidx.core.view.** { *; }
-keep class androidx.core.widget.** { *; }
-keep class androidx.constraintlayout.** { *; }
-keep class androidx.startup.** { *; }
-keep class androidx.security.crypto.** { *; }
-keep class androidx.window.** { *; }
-keep class com.android.internal.policy.** { *; }
-keep class androidx.fragment.** { *; }
-keep class androidx.work.impl.background.** { *; }
-keep class androidx.viewpager2.** { *; }
-keep class androidx.recyclerview.** { *; }
-keep class com.android.internal.policy.** { *; }
-keep class androidx.percentlayout.** { *; }
-keep class androidx.browser.** { *; }
-keep class android.app.** { *; }
-keep class android.view.** { *; }
-keep class android.util.** { *; }
-keep class android.net.** { *; }
-keep class androidx.navigation.** { *; }
# Java
-keep class java.util.** { *; }
If all you want is the specific OneSignal rules
# OneSignal
-keepattributes Signature
-keep class com.onesignal.** { *; }
-keep class com.onesignal.core.** { *; }
-keep class com.onesignal.session.** { *; }
-keep class com.onesignal.user.** { *; }
-keep class com.onesignal.internal.** { *; }
-keep class com.onesignal.debug.** { *; }
-keep class com.onesignal.common.** { *; }
-keep class ** implements com.onesignal.common.modules.IModule { *; }
tbh, this might be enough
# OneSignal
-keepattributes Signature
-keep class com.onesignal.** { *; }
Thanks @IainS1986 for this tip. That got my app back in working order.
What happened?
Updgrading a Xamarin Native to .net-android and .net-ios project.
Added OneSignalSDK.DotnNet/5.0.2
OneSignal.Initialize("MY KEY");
This line then errors with...
Steps to reproduce?
What did you expect to happen?
It initialises.
Relevant log output
Code of Conduct