owca owca - 3 months ago 21
AngularJS Question

Integrate facebook with cordova and angular (Ionic)

I'm trying to add facebook integration to my ionic mobile app that I'm building using cordova. I'm able to get it working either without cordovaa or angular but in no way with both. With the code below, everything goes fine till FB.init gets called after loading all.js . After that, no further code is executed inside _init function, and because of that I cannot subscribe to events or do anything else.

angular facebook directive (uses code from this gist : https://gist.github.com/ruiwen/4722499)

angular.module('facebook', [])
.directive('fb', ['$FB', function($FB) {
return {
restrict: "E",
replace: true,
template: "<div id='fb-root'></div>",
compile: function(tElem, tAttrs) {
return {
post: function(scope, iElem, iAttrs, controller) {
var fbAppId = iAttrs.appId || '';

var fb_params = {
appId: iAttrs.appId || "",
cookie: iAttrs.cookie || true,
status: iAttrs.status || true,
nativeInterface: CDV.FB,
useCachedDialogs: false,
xfbml: iAttrs.xfbml || true
};

// Setup the post-load callback
window.fbAsyncInit = function() {
$FB._init(fb_params);

if('fbInit' in iAttrs) {
iAttrs.fbInit();
}
};

(function(d, s, id, fbAppId) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk', fbAppId));
}
}
}
};
}])

.factory('$FB', ['$rootScope', function($rootScope) {

var fbLoaded = false;

// Our own customisations
var _fb = {
loaded: fbLoaded,
isLoaded : function(){
return this.loaded;
},
authenticated : false,
isAuthenticated : function(){
return this.authenticated;
},
statusUpdated: function(response){
if (response.status == 'connected') {
self.authenticated = true;
alert('logged in');
} else {
alert('not logged in');
}
},
_init: function(params) {

self = this;

if(window.FB) {


// FIXME: Ugly hack to maintain both window.FB
// and our AngularJS-wrapped $FB with our customisations
angular.extend(window.FB, this);
angular.extend(this, window.FB);

// Set the flag
this.loaded = true;

// Initialise FB SDK

FB.init(params);

//THIS CODE IS NOT CALLED
FB.Event.subscribe('auth.statusChange', function(response) {
alert('auth.statusChange event');
});

FB.Event.subscribe('auth.authStatusChange', self.statusUpdated)

if(!$rootScope.$$phase) {
$rootScope.$apply();
}
}
}
}

return _fb;
}]);


My controller :

angular.module('starter.controllers', [])

.controller('StartCtrl', [
'$scope',
'$FB',
'$location',
function($scope, $FB, $location) {
$scope.$watch(function() {
return $FB.isLoaded()
},function(value){

console.log("VALUE",value);
// It needs authentication, this won't work.
if(value){
$scope.facebook_friends = $FB.api('/me/friends', function(response) {
$scope.facebook_friends = response.data;
});
}
},true);

$scope.$watch(function() {
return $FB.isAuthenticated()
},function(value){

alert("VALUE isAuthenticated "+value);
// YEP, this will work.
if(value){
$scope.facebook_friends = $FB.api('/me', function(response) {
$scope.facebook_friends = response.data;
console.log("FRIENDS",response);
});
}
},true);

$scope.FBlogin = function() {
FB.login(null, {scope: 'email'});
};

}
])


index.html :

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, user-scalable=no, width=device-width">
<title>Starter</title>

<link href="lib/css/ionic.css" rel="stylesheet">
<link href="css/app.css" rel="stylesheet">

<script src="lib/js/ionic.bundle.js"></script>

<script src="cordova.js"></script>
<script src="js/angular-fb.js"></script>
<script src="js/app.js"></script>
<script src="js/services.js"></script>
<script src="js/controllers.js"></script>

<!-- cordova facebook plugin -->
<script src="cdv-plugin-fb-connect.js"></script>
<!-- facebook js sdk -->
<script src="facebook-js-sdk.js"></script>
</head>

<body ng-app="starter" animation="slide-left-right-ios7">

<ion-nav-view></ion-nav-view>

<fb app-id='appid'></fb>

</body>
</html>


and app.js

angular.module('starter', ['ionic', 'starter.services', 'starter.controllers', 'facebook'])

.config(function($stateProvider, $urlRouterProvider) {


$stateProvider

.state('start', {
url: "/start",
templateUrl: "templates/start.html",
controller: 'StartCtrl'
})

// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/start');
});

Answer

You should not doing this <script src="facebook-js-sdk.js"></script> actually since it against TOS. Even-though you want to make sure the sdk is loading.

Instead you can try this code below (to make sure you can install cordova-inappbrowser first)

<script>
  function statusChangeCallback(response) {
    console.log('statusChangeCallback');
    console.log(response);
    if (response.status === 'connected') {
      // Logged into your app and Facebook.
      testAPI();
    } else if (response.status === 'not_authorized') {
      // The person is logged into Facebook, but not your app.
      document.getElementById('status').innerHTML = 'Please log ' +
        'into this app.';
    } else {

      document.getElementById('status').innerHTML = 'Please log ' +
        'into Facebook.';
    }
  }
  
  function checkLoginState() {
    FB.getLoginStatus(function(response) {
      statusChangeCallback(response);
    });
  }

  window.fbAsyncInit = function() {
  FB.init({
    appId      : '{your-app-id}',
    cookie     : true,  // enable cookies to allow the server to access 
                        // the session
    xfbml      : true,  // parse social plugins on this page
    version    : 'v2.5' // use graph api version 2.5
  });

  FB.getLoginStatus(function(response) {
    statusChangeCallback(response);
  });

  };

  (function(d, s, id) {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) return;
    js = d.createElement(s); js.id = id;
    js.src = "//connect.facebook.net/en_US/sdk.js";
    fjs.parentNode.insertBefore(js, fjs);
  }(document, 'script', 'facebook-jssdk'));
  
  function testAPI() {
    console.log('Welcome!  Fetching your information.... ');
    FB.api('/me', function(response) {
      console.log('Successful login for: ' + response.name);
      document.getElementById('status').innerHTML =
        'Thanks for logging in, ' + response.name + '!';
    });
  }
</script>

<!--
  Below we include the Login Button social plugin. This button uses
  the JavaScript SDK to present a graphical Login button that triggers
  the FB.login() function when clicked.
-->

<fb:login-button scope="public_profile,email" onlogin="checkLoginState();">
</fb:login-button>

<div id="status">
</div>

To deeper insight

Comments