Pushwoosh / pushwoosh-phonegap-plugin

Pushwoosh PhoneGap Build Plugin
Other
109 stars 139 forks source link

Possible conflicts with Pushy plugin? #356

Open CodeWithOz opened 2 years ago

CodeWithOz commented 2 years ago

We use Pushy as our primary provider of push notifications. We're considering using the segmentation (https://blog.pushwoosh.com/blog/customer-segmentation/) features provided by pushwoosh, so I'm curious to know if there are any potential pitfalls when using both Pushy and pushwoosh and their plugins in the same app bundle (on Android or iOS). Have you attempted something like this before, or are there obvious sources of conflict that would need to be resolved? Battery performance is one thing I have in mind, but maybe there are other concerns too that you may have thought of. Thanks in advance. :)

wfhm commented 2 years ago

Hi @CodeWithOz,

There might be some integration issues both on Android and iOS, however, for both platforms they can be resolved quite easily (using native Java and Obj-C tools though).

Guide for Android:

https://docs.pushwoosh.com/platform-docs/pushwoosh-sdk/android-push-notifications/customizing-android-sdk/android-faq#using-pushwoosh-sdk-with-other-fcm-services

iOS:

https://docs.pushwoosh.com/platform-docs/pushwoosh-sdk/ios-push-notifications/customizing-ios-sdk#custom-unnotificationcenterdelegate

If you face any issues with integrating both Pushwoosh and Pushy SDKs, please feel free to submit a ticket at our Help Center

CodeWithOz commented 2 years ago

@wfhm thanks for the resources. It seems the core idea is to detect the source of the received push, then route that to the correct handler for either push service. Please correct me if I'm wrong. Assuming I'm right, does that mean that the extra handling will not be necessary seeing as Pushy doesn't use FCM by default?

wfhm commented 2 years ago

@CodeWithOz, yes, this is the core idea. If Pushy doesn't use FCM, then there should be no conflicts between the SDKs on Android devices. For iOS, we send pushes via APNs, so, if Pushy uses a custom notification delegate, it might still require creating a proxy as per the guide from my previous response.

CodeWithOz commented 2 years ago

@wfhm thanks for the response. I reached out to Pushy support to get the configuration right and I shared the links you shared above. They highlighted that there'll be issues with iOS due to method swizzling, this was their specific response:

As per iOS, since both Pushy and Pushwoosh depend on APNs, and both try to swizzle the APNs AppDelegate methods. Pushy provides an option to disable swizzling and support multiple push SDKs, but it appears Pushwoosh does not provide such an option for its Cordova plugin. This will lead to an issue where only Pushwoosh or only Pushy are able to register for notifications, and receive notifications sent from one of the platforms only. Unfortunately, the UNNotificationCenterDelegate callbacks are different to the APNs callbacks: didRegisterForRemoteNotificationsWithDeviceToken, didFailToRegisterForRemoteNotificationsWithError, didReceiveRemoteNotification. Since the Pushwoosh iOS SDK is closed source, there is no way to tell if the swizzling can be disabled, nor is it documented in their docs, nor could I find any info about it on the Internet.

So does this pushwoosh Cordova plugin have a way to disabling swizzling (and therefore can support multiple push plugins at once)? Thanks. :)

wfhm commented 2 years ago

@CodeWithOz,

Pushwoosh plugin indeed uses swizzling, and there is no way to disable it otherwise than changing the plugin's source code. However, the plugin swizzles not only the push notification-related methods, but it is also used for initializing Pushwoosh SDK, so by disabling swizzling you simply disallow our SDK's initialization. We will have to research a bit to figure out the best solution to this.

Meanwhile, by any chance did Pushy support provide you with their guide on supporting multiple Push SDKs? I found the guide for native iOS, however I could not find it for Cordova? Knowing how they expect other push SDKs to behave would help a lot, so if you have any links to the docs or code samples if you have any.

CodeWithOz commented 2 years ago

@wfhm thanks for the explanation. The guide they sent was specifically for method swizzling on iOS, maybe that's the same one you found. I haven't found one for cordova ios too, so I've asked them for more info. I'll update this thread when they respond.

pushy commented 2 years ago

Hi @wfhm and @CodeWithOz, Indeed, we believe the only feasible approach for supporting multiple push SDKs on iOS, which all swizzle APNs methods, is to disable swizzling in all Push SDKs, override each APNs callback manually, and then invoke each SDK from each override.

For the Pushy iOS SDK , disabling swizzling is done by executing the following native Pushy iOS SDK method:

// Disable AppDelegate method swizzling
pushy.toggleMethodSwizzling(false)

@wfhm, we would be glad if the Pushwoosh iOS SDK could provide a way to disable APNs method swizzling.

For both SDKs to continue working properly after disabling method swizzling in both SDKs, it would be necessary to override the following APNs methods in the AppDelegate.swift implementation file, making sure to invoke both the Pushy and Pushwoosh SDKs in each override:

// APNs has assigned the device a unique token
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    // Call internal Pushy SDK method
    Pushy.shared?.application(application, didRegisterForRemoteNotificationsWithDeviceToken:deviceToken)

    // Call internal Pushwoosh SDK method
    Pushwoosh.shared?.application(application, didRegisterForRemoteNotificationsWithDeviceToken:deviceToken)
}

// APNs failed to register the device for push notifications
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    // Call internal Pushy SDK method
    Pushy.shared?.application(application, didFailToRegisterForRemoteNotificationsWithError:error)

    // Call internal Pushwoosh SDK method
    Pushwoosh.shared?.application(application, didFailToRegisterForRemoteNotificationsWithError:error)
}

// Device received notification (legacy callback)
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
    // Call internal Pushy SDK method
    Pushy.shared?.application(application, didReceiveRemoteNotification:userInfo)

    // Call internal Pushwoosh SDK method
    Pushwoosh.shared?.application(application, didReceiveRemoteNotification:userInfo)
}

// Device received notification (with completion handler)
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    // Call internal Pushy SDK method
    Pushy.shared?.application(application, didReceiveRemoteNotification:userInfo, fetchCompletionHandler: completionHandler)

    // Call internal Pushwoosh SDK method
    Pushwoosh.shared?.application(application, didReceiveRemoteNotification:userInfo, fetchCompletionHandler: completionHandler)
}

This appears to be the only way for two SDKs which depend on APNs method swizzling to work alongside each other.

wfhm commented 2 years ago

@pushy-me, @CodeWithOz,

There is a way to disable method swizzling in the plugin by making pushwooshUseRuntimeMagic method return NO:

(in PushNotification.m):

**@implementation** UIApplication (InternalPushRuntime)

- (**BOOL**)pushwooshUseRuntimeMagic {
 **return** **NO**;
}

However, there are no publicly available methods to invoke SDK methods in AppDelegate's overrides for the Pushwoosh Cordova plugin. So, first, we have to add a possibility to call internal Pushwoosh methods.

I've created a task to make these changes, but I cannot provide any ETA on it right now. I will update this thread as soon as there is any news.

Textras commented 2 years ago

@wfhm any update on this or estimation of when there might be?

Thank you.

wfhm commented 2 years ago

@Textras @CodeWithOz I still cannot provide you with an ETA, however, we've already started reworking the way swizzling works in our native iOS SDK. After it is done, we'll be able to update the plugin to allow calling internal Pushwoosh methods in AppDelegate's overrides.

Textras commented 1 year ago

Hello, just checking in here. Thanks.