NativeScript / nativescript-facebook

NativeScript plugin, wrapper of native Facebook SDK for Android and iOS
Apache License 2.0
79 stars 50 forks source link

conflict with NativeScript URL Handler Plugin #217

Open patrickl000000 opened 4 years ago

patrickl000000 commented 4 years ago

Hi,

I am using the Facebook plug-in with NativeScript URL Handler Plugin. This is not working in IOS Platform. But the Android is working. Anyone know have this problem and know how to solve it?

handleOpenURL((appURL: AppURL) => { console.log('Got the following appURL', appURL); });

I am enabled the facebok plug-in in App. Above code will be not working Patrick

DimitarTodorov commented 4 years ago

Hi @patrickl000000

Can you please share a bit more info about the app you are trying to build, the type of the flavour Angular/Typescript/Vue, the versions of the dependencies used in the app etc. A complete issue template which is set by default in this repo will give us more information and we will be very likely to help you solve your issue. Also a sample app where we can reproduce the mentioned issue will be really helpful.

alexmeia commented 4 years ago

Hi @DimitarTodorov, I confirm this issue in iOS. I will provide complete information and a demo app in the next days, as you suggest. Meanwhile, my app is core NativeScript with Typescript and these are the dependencies:

"nativescript-facebook": "^4.2.1",
"nativescript-urlhandler": "1.2.2",

If I init the Facebook plugin in app.ts the handleOpenUrl method in the same file is never reached.

daweedm commented 4 years ago

any news on this ?

lini commented 4 years ago

Hi,

I just tried to reproduce this using the demo app in this repository, I just added the nativescript-urlhandler@1.2.2 plugin and then the following lines in app.ts:

handleOpenURL((appURL: AppURL) => {
    console.log('Got the following appURL', appURL);
});

The app compiled and ran on iOS 13.3 and I was able to log in to facebook. Is there something I am missing? If possible, send a small app and steps that can be used to reproduce this reliably. Thanks!

alexmeia commented 4 years ago

Hi @lini, thank you for trying to reproduce the issue. The app compiles and run in iOS with the two plugins, but the handleOpenURL method stop working when nativescript-facebook plugin is added to the app. This means that when the app is open by a URL containing the app registered URL scheme, handleOpenURL is never reached. Removing nativescript-facebook, handleOpenURL works again.

lini commented 4 years ago

Here is what I tried:

import { handleOpenURL, AppURL } from 'nativescript-urlhandler';

handleOpenURL((appURL: AppURL) => {
  console.log('Got the following appURL', appURL);
});
<dict>
    <key>CFBundleURLName</key>
    <string>org.nativescript.demo</string>
</dict>

Is there something I am missing?

daweedm commented 4 years ago

@lini that's the problem, the facebook login is intercepted by the nativescript-handler plugin and not forwarded to the facebook plugin. When looking at the source, we can seed that both plugins overrides some of AppDelegate's methods to catch "open url" actions, that's where te conflict happens

lini commented 4 years ago

Hm, I tried that as well (both Continue with Facebook and Continue with Facebook (Custom)) and the demo worked. I was logged in with Facebook and could log out as well. I did not see a Got the following appUrl.... console log when I logged in. Perhaps the order of the plugins initialization matters? Here is the app.ts file:

import * as application from 'tns-core-modules/application';
import { init, initAnalytics } from "nativescript-facebook";
import { handleOpenURL, AppURL } from 'nativescript-urlhandler';

application.on(application.launchEvent, function (args) {
    init("1771472059772879");
    initAnalytics();
});

handleOpenURL((appURL: AppURL) => {
    console.log('Got the following appURL', appURL);
});

application.run({ moduleName: "app-root" });
daweedm commented 4 years ago

@lini Yes the order of initialization matters (maybe the order of import/require of that plugins), you can't get both plugins working, it's either facebook-login or urlhandler.

I faced a similar conflict with this plugin and nativescript-plugin-firebase which does the same AppDelegate overriding. A solution would be for the plugins developers to align themselves on how to override the AppDelegate (or use a kind of shared service that emits the needed events).

daweedm commented 4 years ago

As a workaround, how could we catch the data from urlhandler and pass them back to this plugin ?

patrickl000000 commented 4 years ago

Hi,

I also try other plugin (name : Nativescript plugin Universal Links). We confirm this plugin cannot working with Facebook plugin. I am get the same result. Anyone Know How to using Universal link or URL Handle with Facebook Login in Nativescript IOS APP?

Patrick

davidmhHuenei commented 4 years ago

Same problem here. Any solution?

asikalove commented 3 years ago

Hi everyone! Any news about issue? I have hit with this problem also. @daweedm do you have example to get around this problem? Any idea how to override the AppDelegate?

daweedm commented 3 years ago

@asikalove

I found that the origin of the conflict was the use of nativescript-plugin-firebase in my case.

I managed to solve this with the following (ugly but working) workaround :

Apply a custom callback handler by overriding the AppDelegate. For this I put the following code at the bottom of the nativescript-plugin-firebase/firebase.ios.js file.

Disclaimer : this was a quick fix to get a prototype working quickly. For a "real" project, editing dependencies source files directly is a bad habit.

(function () {
                    function extractAppURL(urlParam) {
                        if (!!urlParam) {
                            var url_1 = urlParam.toString(),
                            params = new Map(), urlWithPath = url_1.indexOf('//') < url_1.length - 2,
                            urlWithParams = url_1.indexOf('?') !== -1, path = urlWithPath ? url_1.substring(url_1.indexOf('//') + 2,
                            urlWithParams ? url_1.indexOf('?') : url_1.length) : null,
                            parameters = url_1.substring(url_1.indexOf('?') + 1).split('&');
                            if (urlWithParams) {
                                for (var i = 0, len = parameters.length; i < len; i++) {
                                    var paramData = parameters[i].split('=');
                                    params.set(paramData[0], paramData[1] ? paramData[1] : null);
                                }
                            }
                            return {
                                params: params,
                                path: path,
                                toString: function () {
                                    return url_1;
                                }
                            };
                        } else {
                            return null;
                        }
                    }

                    getAppDelegate().prototype.applicationOpenURLOptions = function (application, url, options) {
                        if (getAppDelegate().prototype.___DS_IOS_HANDLER) {

                            FBSDKApplicationDelegate.sharedInstance.applicationOpenURLSourceApplicationAnnotation(application, url, options.valueForKey(UIApplicationOpenURLOptionsSourceApplicationKey), options.valueForKey(UIApplicationOpenURLOptionsAnnotationKey));

                            var lastArgument = arguments[arguments.length - 1];
                            var previousResult = lastArgument !== options ? lastArgument : undefined;
                            if (!previousResult) {
                                var appURL_1 = extractAppURL(url.absoluteString);
                                if (appURL_1 != null) {
                                    setTimeout(function () { return getAppDelegate().prototype.___DS_IOS_HANDLER(appURL_1); });
                                }
                                return true;
                            }
                            return previousResult;

                        }
                    };

                    getAppDelegate().prototype
                    .applicationContinueUserActivityRestorationHandler = function (application, userActivity, restorationHandler) {
                        if (getAppDelegate().prototype.___DS_IOS_HANDLER) {
                            if (userActivity.activityType === NSUserActivityTypeBrowsingWeb) {
                                var appURL_2 = extractAppURL(userActivity.webpageURL);
                                if (appURL_2 !== null) {
                                    setTimeout(function () { return getAppDelegate().prototype.___DS_IOS_HANDLER(appURL_2); });
                                }
                            }
                            return true;
                        }
                    };

                })();

Then, wherever you need, you can register a custom callback in your app source code, like this :

require('tns-core-modules/application/application').ios.delegate.prototype.___DS_IOS_HANDLER = (url) => {
            console.log('GOT url from ___DS_IOS_HANDLER', url);
            setTimeout(() => this.ngZone.run(() => this.handleOpenURL(url)));
        };

It may not solve your issue because mine was due to the use of nativescript-plugin-firebase in my project.

The workaround is simple but the issue itself is vicious, I spent a whole day searching for the reason why this damn plugin was not working.

Good luck.