When attempting to login to facebook in my app, I am experiencing a few strange behaviors.
Current stack information:
Strange Behaviors:
login
event never fires when returning from Facebook login on device.login
event sometimes doesn't fire when returning from Facebook login on simulator.I'm actually the original contributor of the setLoginBehavior
functionality of the module, though Facebook's stance seems to have changed since that contribution from "We always want you to use browser." to "We always want you to use Native.". I'm posting this question here in case someone has some insight - while I wait for an answer I will be back into the source for that module.
The only factor that I can imagine might be different from most apps is that I am using Kris Kowals Q. Here follows the code, almost verbatim from my app.
The actual function that does the login:
// linkingmodule.js
exports.linkFacebook = function() {
var Q = require('vendor/q'),
response = Q.defer(),
facebook = require('facebook'),
permissions = ['public_profile', 'user_friends', 'user_likes'];
facebook.initialize();
facebook.setLoginBehavior(facebook.LOGIN_BEHAVIOR_NATIVE);
facebook.permissions = permissions;
facebook.addEventListener('login', function fireLogin(e) {
if(!e.success || !facebook.loggedIn) {
return response.reject({
status: e.code,
error: e.error
});
}
response.resolve({
uid: e.uid,
data: e.data,
token: facebook.getAccessToken()
});
});
facebook.authorize();
return response.promise;
};
The alloy controller function that calls the login function:
// login.js
function facebookLogin() {
var remote = require('linkingmodule');
remote.linkFacebook().
then(function(r) {
// do some things
}).
fail(function(e) {
console.error(e);
throw 'Unable to login with Facebook.';
});
}).
fail(function(e) {
console.error('Facebook login failed');
console.error(e);
});
}
I have chalked this up to a bug in the Titanium module SDK, specifically Ti.fireEvent
. My investigation ended with the Facebook Module, but all events within the module appeared to be sent and received as expected. Only, when Ti.fireEvent
was called, it was not received in the JS app "under some circumstances". The possibility remains of a block retain cycle within the facebook module, but I was not able to solve it.
Here is my workaround:
function facebookLogin() {
var Q = require('vendor/q'),
response = Q.defer(),
fb = require('facebook'),
permissions = ['public_profile', 'user_friends', 'user_likes'];
var checkLoginStatus, fireLogin;
checkLoginStatus = function(e) {
Ti.App.removeEventListener('resumed', checkLoginStatus);
fb.removeEventListener('login', fireLogin);
// login often doesn't fire, so let's check on resumed as well
if(fb.loggedIn) {
return response.resolve({
uid: fb.uid,
data: null,
token: fb.getAccessToken()
});
}
console.log('resumed and found that are NOT logged in');
return response.reject({
status: -1,
error: 'Did not work.'
});
};
fireLogin = function(e) {
fb.removeEventListener('login', fireLogin);
Ti.App.removeEventListener('resumed', checkLoginStatus);
if(!e.success || !fb.loggedIn) {
return response.reject({
status: e.code,
error: e.error
});
}
response.resolve({
uid: e.uid,
data: e.data,
token:fb.getAccessToken()
});
};
Ti.App.addEventListener('resumed', checkLoginStatus);
fb.addEventListener('login', fireLogin);
fb.initialize();
fb.setLoginBehavior(fb.LOGIN_BEHAVIOR_NATIVE);
fb.permissions = permissions;
fb.authorize();
return response.promise;
}
So, basically keep listening for the login
event - it fires correctly under "some circumstances". But also listen for App.resumed
. Whichever fires first, cancel all listeners, and check for logged in status.