Facebook Native not working in Browser

Hello,

i moved from Ionic 1.* to Ionic 2.* and installed the Facebook4 Plugin.

Now i could see that there is no src/browser folder. Anyway, ive tried calling
Facebook.browserInit("");

within platform.ready but it seems to be broken. It throws an Exception

 angular2-polyfills.js:528 Unhandled Promise rejection: Object {error: "cordova_not_available"} ; Zone: angular ; Task: Promise.then ; Value: Object {error: "cordova_not_available"}

and in the console
TypeScript error: app/pages/facebook/facebook.ts(24,20): Error TS2346: Supplied parameters do not match any signature of call target.

What may be wrong? Its working fine in android.

i’ve made a validation with if (this.platform.is(‘cordova’)) { } else { Facebook.browserInit(…); }

The plugin does not support the browser platform.

Looking into the source of this, it seems that it only supports ios and android.

Its annoying since there is a browerinit function and a Browser JavaScript. The original cordova Facebook has Browser Support. The docs say that Browser init has to be called before

@mhartington: This is error is also happening with cordova-plugin-badge. More details here: https://github.com/driftyco/ionic-native/issues/135, but it might be a bigger issue with multiple plugins.

Now another issue happened.

When using the Facebook Plugin gapdebug gives the following warning in IOS (Works great in Android)

[Warning] Native: deviceready did not fire within 2000ms. This can happen when plugins are in an inconsistent state. Try removing plugins from plugins/ and reinstalling them. (app.bundle.js, line 63888)

And when i go to the Facebook Component, its not working. NOt even logs or something.

import {Page, NavController, Platform} from 'ionic-angular';
import {Facebook} from 'ionic-native';
import {OnInit} from 'angular2/core';

@Page({
    templateUrl: 'build/pages/facebook/facebook.html',
})
export class FacebookPage {

    feed:Array<any>;

    constructor(public nav:NavController, public platform:Platform) {
        this.platform = platform;
        platform.ready().then(() => {

        });
    }


    ngOnInit() {
        console.log("ngOnInit called");
        try {
            this.fbLogin();
        } catch (error) {
            console.log("error in cons", error);
        }
    }

    login() {
        try {
            if (this.platform.is('cordova')) {
                return Facebook.login(['email', 'publish_actions']).then(
                    (success) => {
                        console.log("facebook login success", success);
                        return success;
                    },
                    (error) => {
                        console.log("facebook error login", error)
                        return error;
                    }
                )
            }
            else {
                return Promise.reject("Please run me on a device");
            }
        } catch (error) {
            console.log(error);
            return Promise.reject(error);
        }
    }

    validateLogin() {
        return Facebook.getLoginStatus().then(
            (status) => {
                console.log("current status: ", status);
                try {
                    Facebook.showDialog({method: "share"}).then((result) => {
                        console.log("Posted. ", result);
                    });
                } catch (error) {
                    console.log(error);
                }
                return status;
            },
            (error) => {
                console.log("fb status error", error);
                return error;
            }
        );
    }

    fbLogin() {
        this.login().then(
            (sucess) => {
                this.validateLogin().then(
                    (success) => {
                        try {
                            Facebook.api("/myfeed/feed?fields=id,caption,created_time,description,from,icon,link,message,message_tags,name,object_id,picture,shares,source,story,story_tags,to,type,status_type,admin_creator,full_picture,child_attachments,application,with_tags,likes.limit(1).summary(true),sharedposts,comments.limit(1).summary(true)", ["public_profile"]).then(
                                (result) => {
                                    console.log("FB Result: ", result);

                                    let results = [];

                                    for (var i = 0; i < result.data.length; i++) {

                                        console.log("fb data=", result.data[i]);
                                        results.push(result.data[i]);
                                    }
                                    this.feed = results;
                                }, (error) => {
                                    console.error("Failed: ", error);
                                }
                            );
                        } catch (error) {
                            console.log(error);
                        }
                        return success;
                    },
                    (error) => {
                        console.log("after login error", error);
                        return error;
                    }
                );


            },
            (error) => {
                console.log("error in fb login", error);
            }
        )
    }

   
}

The Template is simple, just for testing purpose:

<ion-content class="facebook">
  <button (click)="fbLogin()">FACEBOOK LOGIN</button>

  <ion-list>
    <ion-item class="coupons" *ngFor="#fb of feed">

      <div *ngIf="!!fb.id" >{{fb.id}}</div>
      <div *ngIf="!!fb.message">{{fb.message}}</div>
    </ion-item>
  </ion-list>
</ion-content>

Any news why its not working on IOS? Browser doesnt matter right now

Do you know any project that support browser and cordova for angular2?

look here instead. It should be supported:

Works fine with Ionic 1.

Anyone had luck with browser support and ionic-native?

any luck on this? for ionic 1 I utilized a sort of an extension installed with bower that worked like a charm, the cordova-facebook-connect-plugin.js

I’m trying to think of a way to convert this to Ionic 3 (Typescript) or load into my app somehow.

I found a way to make it work! maybe its not the “right” way but it does work!

cordova-facebook-connect-plugin.js

/*global window, document, FB */
(function () {
    'use strict';

	/*
	* @author Pat Nolan - Modifed from the original Author Ally Ogilvie
	* @copyright Wizcorp Inc. [ Incorporated Wizards ] 2014
	* @file - facebookConnectPlugin.js
	* @about - JavaScript interface for PhoneGap bridge to Facebook Connect SDK
	*
	*
	*/

	document.addEventListener('DOMContentLoaded', function(e) {
		//console.log('DOMContentLoaded', e);
		var facebookConnectPlugin = {};

		if (!window.cordova || window.cordova && window.cordova.platformId === 'browser') {
			console.log('no cordova');

			facebookConnectPlugin = {

				getLoginStatus: function (s, f) {
					// Try will catch errors when SDK has not been init
					try {
						FB.getLoginStatus(function (response) {
							s(response);
						});
					} catch (error) {
						if (!f) {
							console.error(error.message);
						} else {
							f(error.message);
						}
					}
				},

				showDialog: function (options, s, f) {
					var opts = {
						name: '',
						message: '',
						caption: '',
						description: '',
						href: '',
						picture: ''
					}, opt = '';

					for(opt in options) {
						if(options.hasOwnProperty(opt)) {
							opts[opt] = options[opt];
						}
					}

					// Try will catch errors when SDK has not been init
					try {
						FB.ui(options,
						function (response) {
							if (response && (response.request || !response.error_code)) {
								s(response);
							} else {
								f(response);
							}
						});
					} catch (error) {
						if (!f) {
							console.error(error.message);
						} else {
							f(error.message);
						}
					}
				},
				// Attach this to a UI element, this requires user interaction.
				login: function (permissions, s, f) {
					// JS SDK takes an object here but the native SDKs use array.
					var permissionObj = {};
					if (permissions && permissions.length > 0) {
						permissionObj.scope = permissions.toString();
					}

					FB.login(function (response) {
						if (response.authResponse) {
							s(response);
						} else {
							f(response.status);
						}
					}, permissionObj);
				},

				getAccessToken: function (s, f) {
					var response = FB.getAccessToken();
					if (!response) {
						if (!f) {
							console.error('NO_TOKEN');
						} else {
							f('NO_TOKEN');
						}
					} else {
						s(response);
					}
				},

				/* jshint ignore:start */
				logEvent: function (eventName, params, valueToSum, s, f) { 
					// AppEvents are not avaliable in JS.
					s();
				},

				logPurchase: function (value, currency, s, f) { // jshint ignore:line
					// AppEvents are not avaliable in JS.
					s();
				},
				/* jshint ignore:end */

				logout: function (s, f) {
					// Try will catch errors when SDK has not been init
					try {
						FB.logout( function (response) {
							s(response);
						});
					} catch (error) {
						if (!f) {
							console.error(error.message);
						} else {
							f(error.message);
						}
					}
				},

				api: function (graphPath, permissions, s, f) {
					// JS API does not take additional permissions

					// Try will catch errors when SDK has not been init
					try {
						FB.api(graphPath, function (response) {
							if (response.error) {
								f(response);
							} else {
								s(response);
							}
						});
					} catch (error) {
						if (!f) {
							console.error(error.message);
						} else {
							f(error.message);
						}
					}
				},

				// Browser wrapper API ONLY
				browserInit: function (appId, version) {
					if (!version) {
						version = 'v2.0';
					}
					FB.init({
						appId      : appId,
						cookie     : true,
						xfbml      : true,
						version    : version
					});
				}
			};

			// Bake in the JS SDK
			if (!window.FB) {
				console.log('launching FB SDK');
				var scriptEl = document.createElement('script'),
					fbRootEl;
				scriptEl.src = document.location.protocol !== 'file:' ? '//connect.facebook.net/en_US/sdk.js' : 'http://connect.facebook.net/en_US/sdk.js';
				scriptEl.async = true;

				if(!document.getElementById('fb-root')) {
					fbRootEl = document.createElement('div');
					fbRootEl.id = 'fb-root';
					fbRootEl.appendChild(scriptEl);
					document.body.appendChild(fbRootEl);
				} else {
					document.body.appendChild(scriptEl);
				}

				scriptEl.onload = function() {
					console.log('FacebookSDK loaded from server');
				};
			}

			window.facebookConnectPlugin = facebookConnectPlugin;
		} 
	});

})();

copy this file into your src/assets/js folder

I created a SocialService that will make use of the object window.facebookConnectPlugin when not in Cordova as follows:

import { Injectable } from '@angular/core';

import { Http, Headers, RequestOptions, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';

import { Events, Platform } from 'ionic-angular';

import { Config } from '../../config/config';

import {Facebook, FacebookLoginResponse} from '@ionic-native/facebook';

declare var cordova:any;
declare var window:any;

@Injectable()
export class SocialService {

	mode:string = 'dev';

	ready:boolean = false;
	isCordova:boolean;
	isIOS:boolean;
	isAndroid:boolean;

	fbPermissions:any[];

	constructor(
		public config:Config, 
		public http:Http,
		public events:Events,
		public plt:Platform,
		public fb:Facebook){

		this.isAndroid = plt.is('android');
    	this.isCordova = plt.is('cordova');
    	this.isIOS = plt.is('ios');

    	this.fbPermissions = ['public_profile', 'user_friends', 'email'];

    	let fbInit = ()=>{
    		window.facebookConnectPlugin.browserInit(config.FB.appid, config.FB.version);
    	}

    	plt.ready()
    	.then(source=>{
    		console.log(source);

    		if(this.isCordova){

    		}else{
    			console.log(window);
    			if(!window.facebookConnectPlugin){
    				setTimeout(()=>{
    					//console.log(window.facebookConnectPlugin);
    					fbInit();
    				}, 2000);
    			}else{
    				//console.log(window.facebookConnectPlugin);
    				fbInit();
    			}
    		}
    	})
    	.catch(err=>{

    	});

		
	}

	fbLogin():Promise<any>{
		if(this.isCordova){

		}
		else{

			return new Promise((resolve, reject)=>{
				window.facebookConnectPlugin.getLoginStatus(
				(res)=>{
					console.log(res);
					if(res.status == 'connected') {
						resolve(true);
						return;
					}else{
						window.facebookConnectPlugin.login(this.config.FB.permissions, 
						res=>{
							console.log(res);
							resolve(true);
						},
						err=>{
							console.log(err);
							reject(err);
						})
					}
					//resolve(res);
				},
				(err)=>{
					console.log(err);
					reject(err);
				});
			});

		}

	}
}

in your pages you just call the service method accordingly!

my login.ts

import {SocialService} from '../../providers/native/social-service';
@Component({
  selector: 'page-login',
  templateUrl: 'login.html'
})
export class LoginPage {

constructor(public socialService:SocialService){
}

fbLogin(){
    this.socialService.fbLogin()
    .then(res=>{})
    .catch(err=>{});
  }

}

hope it helps!
Cheers

1 Like

Thank you Tattivitorino, the cordova-facebook-connect-plugin.js kicks ass :slight_smile:

1 Like

In order the plugin to work for the browser you should add platform browser and run it:
ionic cordova platform add browser
and run it:
ionic cordova run browser
otherwise it wont work with: ionic serve

2 Likes

This is terrible advice as most Cordova plugins just don’t have a browser implementation.