Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Facebook 3.1.1 SDK breaks A LOT
Started by haakon Dec 29 2012 08:39 PM

- - - - -
133 replies to this topic
[TOPIC CONTROLS]
Page 3 of 6 1 2 3 4 5 »
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#51

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

Wow. No kidding. The well placed facebook.logout actually solved the CASE 6. Maybe it will solve CASE 5 too. Is this what you did, haakon, to work this out? I do remember seeing a post somewhere about the key to solving Facebook problem is the use of facebook.logout. The problem was, I added the facebook.logout everywhere early on, which wildly exacerbated my problem and complicated the debug process for me.

Here's the solution I found for my app:

1) add facebook.logout only inside if-statement of an event.phase ~= "login"

2) call facebook.login with permissions only once after the app is launched
Note: actually, with my app, I might be call facebook.login with permissions only once per device. Once a user give permission on a given device, until the device is wiped, I might not be calling the login with permission. I need to investigate a bit more before I implement this on all FB related calls, but I suppose it's enough info for anyone who might be seeking solution here, so I won't be updating this note.

3) after facebook.login with permissions is called once (and after the user permits the app's use of Facebook access), call facebook.login without permission

I think that was all it took. I'm not seeing the problem Tom mentions in his post #47, so who knows, my app might come across that issue (hopefully not, though.) I can also still think of other paths the user may take that could possibly bring back the Error 400 (such as de-authorizing/removing the app directly from the user's Facebook account while the app is still in suspend mode), but perhaps that's an edge case I can live with (and perhaps it won't even cause error 400, who knows -- I'm too tired to test every possible case that I can think relating to my FB fiasco at this point.) I'm going to move on and work on finishing up my app (which is way late than I hoped.)

Tom or anyone else who is dealing with this error, please let me know if you find other solution(s). I would also like to hear if there are other error case(s) that cannot be solved with the solution I employed. It can only help us get our Facebook components working smoothly with the updated Facebook SDK.

Naomi
uid: 67217 topic_id: 34416 reply_id: 140815


[TOPIC: post.html]
#52

Tom

[GLOBAL: userInfoPane.html]
Tom
  • Moderator

  • 1,480 posts
  • Corona Staff

Hi Naomi,

Thank you very much for your hard work here and outlining the different cases you're come across. I haven't had time to get back on this but I hope too in the next day or two. It sounds like you confirmed my thoughts that issuing permissions multiple times on the same device is the source of the FB 400 error.

I'm a little confused why you were getting the FB error in your previous post when you only called login once with permissions. You mentioned adding that logout fixed the issue -- can you give a little more information where you added that code so I can construct a test case to see what's going on?

Maybe it would be better to continue the conversation via email and not keep adding to this thread. We can update the thread later when we come to a conclusion about the issue. tom at coronalabs.com

-Tom
uid: 7559 topic_id: 34416 reply_id: 140902


[TOPIC: post.html]
#53

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

Hi Tom, I'll follow up with you via email.

Naomi

Edit: Just so I don't mislead people, I have to add this:
CASE 7 failed, just the same way CASE 5 failed. CASE 7 is equivalent to CASE 5. With CASE 7, only difference from CASE 6 is that the first time user wants to post to FB, he/she needs to login to FB, because he/she skipped on connecting to FB in Scene A. Login call with permission parameter is called only once (just like it does with CASE 5). So I guess facebook.logout isn't helping. Now what? Dunno what to do. I'll follow up with Tom and see if he can identify where the problem is and find a fix for it...
uid: 67217 topic_id: 34416 reply_id: 140912


[TOPIC: post.html]
#54

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

BTW, maybe CASE 6 worked fine every time except that I thought it failed when in fact I was testing CASE 7. The next day, when I tried CASE 6 again, it worked (because perhaps it never failed.)

Anyhow, here's how CASE 7 went.

CASE 7: Error 400 (app built with1013, installed on a freshly wiped device, with a new user who has not authorized the app on FB)

1 (scene A): facebook.login( myAppID, myFBRegListener, { ""email", "publish_actions" } )
* User skips on connecting to FB

2 (scene D): facebook.login( myAppID, FBLoginListener, { "email", "publish_actions" } )
* The user plays a few games and makes a new high score, and decides to post the score on FB
* The app invokes facebook.login( myAppID, FBLoginListener, { "email", "publish_actions" } )
* Upon successful login to FB, the app invokes facebook.request( "me" )
* Upon successful receipt of the json object with the user data, the app saves the data
* Upon successful save, the app invokes facebook.request("me/scores" , "POST", attachment)
* Upon successful post to FB, the app invokes facebook.request(myAppID .. "/scores")
* Upon successful retrieval of score data json object from FB, the app displays the friends scores
* The user then proceed to play another game.

3 (scene D): facebook.login( myAppID, FBScoreListener )
* The user plays a game and beats the previous high score.
* The user chooses to post it to FB and see FB friends score, which invokes facebook.login( myAppID, FBScoreListener )
* Upon successful login to FB, the app invokes facebook.request("me/scores" , "POST", attachment)
* Upon successful post to FB, the app tries to invoke facebook.request(appID .. "/scores") but fails with Error: HTTP status code: 400
uid: 67217 topic_id: 34416 reply_id: 140954


[TOPIC: post.html]
#55

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

@olav.morkrid, I don't think it hurts to submit a bug report. About Apple, I doubt it will reject your apps because of this particular leak you found (unless your app accumulates this leak very quickly for some reason.) How often & how quickly do you add the 64 bytes to the memory during the time the user uses your app? If it adds up very rapidly and ends up crashing the app every time you run your app, then it would be a no go (meaning, Apple won't approve it.) But if it takes hours and months of uninterrupted use of your app, then Apple probably won't notice.

@Tom, here's the update to my saga. I was able to sort out the user flow by removing facebook.logout entirely and calling facebook.login only once at the time of entry to the Scene C with rows & rows of FB friends (which the user enters from Scene B with FB Connect/Friends button. And sorry about changing the scene names -- I felt I needed to introduce scene C to make my test case easier to understand.)

Anyhow, thanks to your detailed post on #47, I decided the evil is with using facebook.login for the multiple of facebook.request the app makes in a quick succession where the likelihood of user signing out in-between is almost nil. Taking this measure solved the CASE 2 & CASE 4 issue completely. It flows perfectly well, just like how I wanted to have it. With this fix, the user experience is very much the same as the successful user experience achieved with the CASE 4 using daily build 990.

THAT SAID... I don't know how I may work around the last bit of problem. I still get Error Status 400 under the following scenario. Can you think of any reason why it's still giving out this error? Is this a Corona bug, or is this a Facebook bug, or am I doing something wrong?

CASE 5: Error 400 (app built with1013, installed on a freshly wiped device with a new user)

1 (scene A): facebook.login( myAppID, myFBRegListener, { ""email", "publish_actions" } )
* User skips the FB Connect button

2 (scene B): go to scene C
* Because the user has not supplied FB credentials, this scene displays FB Connect button
* Tapping on the FB Connect button transitions the scene to C (using storyboard API)

3 (scene C): facebook.login( myAppID, myFBLoginListener, { "email", "publish_actions" } )
* Upon entering this scene, facebook.login( myAppID, myFBLoginListener, { "email", "publish_actions" } ) is invoked.
* Upon successful login, facebook.request( "me" ) is invoked
* Upon successful receipt of the json object with the user data, the app saves the data
* Upon successful save, facebook.request( "me/friends" ) is invoked
* Upon fetching the friends list, the scene C successfully displays the friends list

4 (scene C): facebook.login( myAppID, FBPostListener )
* User taps on a friend
* If the friend is already registered with the app, the app initiates a match game between the players
* If the friend is not already registered with the app, facebook.login( myAppID, FBPostListener ) is invoked
* Upon successful login, facebook.showDialog( "feed", attachment ) is invoked

5 (scene C): facebook.showDialog( "feed", attachment )
* This brings up the FB dialog without a problem
* The user taps on Share button, and it posts on the friends wall.
* The user now exits scene C and returns to scene B

6 (scene B): go to scene C
* Now that the app has the user's FB credential, the button changes from FB Connect to FB Friend
* Tapping on the FB Friend button sends the user to scene C again

7 (scene C): facebook.login( myAppID, myFBListener )
* Now that the app has the user's FB credential, entering the scene invokes facebook.login( myAppID, myFBListener ) instead of facebook.login( myAppID, myFBLoginListener, { "email", "publish_actions" } )
* Then the dreadful Error: HTTP status code: 400 shows up.
* User sees a message from the app stating that it could not log in to Facebook.
* Tapping on the message sends the user back to scene B.

8 (scene B & C)
* This turns into never ending loop -- i.e., step 6 and step 7 can repeat over and over
* At this point, the user kills the app by tapping on home button, then double tapping on home button, and then closing the app.

9 (scene B) go to scene C
* After the app is restarted, the user goes straight to Scene B
* The app remembers the user's FB credential and displays FB Friend button
* Tapping on the FB Friend button sends the user to scene C

10 (scene C): facebook.login( myAppID, myFBListener )
* Upon entering the scene, facebook.login( myAppID, myFBListener ) is invoked (just like step 7 above)
* Upon successful login, the listener invokes facebook.request( "me/friends" )
* Upon fetching the friends list, the scene C successfully displays the friends list

After this, moving between scenes B & C causes no error.

How do you think this problem can be solved?

I'm not sure if this means anything, but I also noticed something odd. ( Edit: Could this be related to the phantom Session Bug that haakon mentions in post #3...? ) After I had the never ending loop in step 8, I left the device idle for a while without killing it (mainly because I was writing up this post). And then before killing the app, I tapped on Friend button once again. It brought up FB permission screen. I don't know why I didn't tap on Okay for the permission request, but I didn't. I just killed the app right there and then, which brought me to step 9. Anyhow, it still makes very little sense why Error 400 occurs. I just hope you can identify the issue here, because I can't think of any work around that makes sense.

Naomi

Saga continues... This is getting really long, but here's another case where it manifests exactly the same problem. I believe the issue is clear enough at this point, and I'd very much like to hear what you suggest I do with Facebook feature. It really isn't going to work for me the way it behaves. (Unless, I suppose, I bring back that awkward facebook.logout calls or revert back to daily build 990.)

------------------------------------------------------------------------------------------
EDIT: CASE 6 actually works perfectly fine. It appears that I was testing some other path, thinking it was this particular path I was taking. Please see my update in post #55.
------------------------------------------------------------------------------------------

CASE 6: Error 400 (app built with1013, installed on a freshly wiped device)

1 (scene A): facebook.login( myAppID, myFBRegListener, { ""email", "publish_actions" } )
* User taps on the FB Connect button, which invokes facebook.login( myAppID, myFBRegListener, { ""email", "publish_actions" } )
* Upon successful login, facebook.request( "me" ) is invoked
* Upon successful receipt of the json object with the user data, the app saves the data and go to next scene (using storyboard API)

2 (scene D): facebook.login( myAppID, FBScoreListener )
* The user plays a few games and reaches a new high score.
* The user has a choice to post his/her score and see FB friends scores
* The user chooses to do so, and the app invokes facebook.login( myAppID, FBScoreListener )
* Upon successful login to FB, the app invokes facebook.request("me/scores" , "POST", attachment)
* Upon successful post to FB, the app invokes facebook.request(myAppID .. "/scores")
* Upon successful retrieval of score data json object from FB, the app displays the friends scores
* The user then proceed to play another game.

3 (scene D): facebook.login( myAppID, FBScoreListener )
* The user plays a game and beats the previous high score.
* The user chooses to post it to FB and see FB friends score, which invokes facebook.login( myAppID, FBScoreListener )
* Upon successful login to FB, the app invokes facebook.request("me/scores" , "POST", attachment)
* Upon successful post to FB, the app tries to invoke facebook.request(appID .. "/scores") but fails with Error: HTTP status code: 400

From then onward, the app performs all non-FB related tasks, but it returns Error 400 for anything FB. Accessing Friends List in Scene C fails with Error 400 as well.

However, once I kill and restart the app, everything normalizes, and posting high scores one game after the other no longer fails. Friends List in Scene C can also be accessed and used as expected.

There is a bug somewhere, but at this point, I'm pretty sure the bug is caused either by the updated Facebook SDK or by how Corona integrated it.
uid: 67217 topic_id: 34416 reply_id: 140589


[TOPIC: post.html]
#56

haakon

[GLOBAL: userInfoPane.html]
haakon
  • Contributor

  • 188 posts
  • Enterprise

Ok, Tom, if you find out that this is indeed a bug with the Facebook SDK, please let me know the exact steps to reproduce, and possibly an xcode test project (not tied to corona). I just went off a Skype meeting with Facebook, and I mentioned that we're having some problems with the latest ios sdk. They'd like to look into it if it turns out to be a bug in the SDK.

One more thing. Why is it not possible to completely log out of facebook in corona? when calling facebook.logout(), I expect that the next time I call facebook.login(), I'm presented with the login dialog where I enter email and password. Instead I'm sent directly to the authorize screen. This makes it impossible to use 2 or more Facebook accounts in a Corona game.
uid: 21746 topic_id: 34416 reply_id: 141258


[TOPIC: post.html]
#57

olavm

[GLOBAL: userInfoPane.html]
olavm
  • Contributor

  • 138 posts
  • Corona SDK

@Corona: Since there seems to be cleanup work going on with Facebook, you guys should make your Facebook SDK handle things gracefully if the user revokes access to an app.

Do the following:

1. Start the app and do something that requires Facebook (wall post, etc.)
2. Log on to Facebook from a computer, and revoke access to the app for the user in question
3. Try to repeat step 1.

Now, things like "HTTP 400" or an "Access revoked" JSON-object will be returned, and us poor developers have to manually do facebook.logout() and redo the facebook.login() cycle in an attempt to set things straight.

Instead, Corona should elegantly do under the hood what it must to automatically present the user with Facebook's "Grant app access to Facebook" page again. The developer shouldn't have to handle this case at all.

If access is revoked, the "Grant access" page should appear automatically the next time the user tries to use Facebook. Simple as that .
uid: 73434 topic_id: 34416 reply_id: 141259


[TOPIC: post.html]
#58

Tom

[GLOBAL: userInfoPane.html]
Tom
  • Moderator

  • 1,480 posts
  • Corona Staff

@olav.morkrid,

I think returning the error code indicating that the user revoked the permission is the right thing to do instead of logging back in to the user's account automatically. As a user of an app if I revoke permission, it may mean I don't want your app to access my account. Your app should recognize that and ask the user if he/she still wants to enable Facebook.

Maybe we can handle things better but going through the extra steps should be required (just my opinion).

Not all Facebook 400 errors are because of problems in Corona. From searching the Internet, that error is a general error for things Facebook doesn't like (e.g., posting to many times within a short period of time). I'm still looking into the errors that have been reported here so I haven't ruled anything out yet.

@haakon,
It's my view that logging out of Facebook using the Corona logout API just affects the Corona app. Facebook's SSO (single sign on) means it uses the current account that's active on the device. If you are signed into one Facebook account using the Facebook app, I wouldn't expect signing out of a Corona app would sign you out of the Facebook app. You would need to sign out of your account (Facebook app) to sign into another account with the Corona app. I believe this is built in to the Facebook SDK.

Like I said before, we are still looking into this.

-Tom
uid: 7559 topic_id: 34416 reply_id: 141260


[TOPIC: post.html]
#59

haakon

[GLOBAL: userInfoPane.html]
haakon
  • Contributor

  • 188 posts
  • Enterprise

Tom, I tested this just now using the xcode simulator. It has no Facebook app. I also checked under Settings => Facebook, and I have no credentials entered there. I know our support is getting asked about this frequently, so it's obvious that the users too expects logout to make it possible to use a different Facebook account when logging in again.

I'd say this needs to be handled by Corona.
uid: 21746 topic_id: 34416 reply_id: 141262


[TOPIC: post.html]
#60

haakon

[GLOBAL: userInfoPane.html]
haakon
  • Contributor

  • 188 posts
  • Enterprise

And here's how you should implement it:

http://stackoverflow.com/questions/13457625/facebook-ios-sdk-logout

You need to clear the safari cookie when facebook.logout() is called.

EDIT - there is a sample project in the facebook sdk download, "SwitchUser" that may give you an idea:

"From your context, I'm assuming your device(s) does not have the Facebook app installed nor do you expect to use iOS 6 system authentication which would leave the default login behavior to use Safari. If you were to clear the Safari cookies, that should work but for a smoother experience in your scenario you should use the FBSession openWithBehavior:completionHandler: method and specify a behavior of FBSessionLoginBehaviorForcingWebview so that it uses the inline webview dialog for authentication.

See the SwitchUserSample in the Facebook iOS SDK for an example since that sample demonstrates an app that can toggle between multiple accounts."
uid: 21746 topic_id: 34416 reply_id: 141264


[TOPIC: post.html]
#61

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

Regarding the Error 400 caused by posting too many times within a short period of time, I believe it isn't the cause for CASE 5 or CASE 7. If it is, then why will it not trigger the error again after restarting the app? For example, once the app gets error under CASE 7 and the app is restarted, posting high score one after the other does not trigger Error 400. Every high score gets posted to FB and friends scores are retrieved every time thereafter.

BTW, I found that wiping the device is not necessary for this error to occur. I moved on to install the app, go through CASE 7, restart the app and normalize the app, and then delete the app (without logging out of FB and without de-authorizing the app from the user's Facebook account,) reinstall the app, go through CASE 7 again, and the exact same error occurs in the exact same way.

Naomi

uid: 67217 topic_id: 34416 reply_id: 141268


[TOPIC: post.html]
#62

olavm

[GLOBAL: userInfoPane.html]
olavm
  • Contributor

  • 138 posts
  • Corona SDK

@Tom: Maybe I was unclear. I'll try to explain my view on this again:

If access is revoked, and the user tries to use Facebook functionality, then the user should be presented with Facebook's standard "Do you want to grant access to this app?" again, without any unnecessary or confusing error dialogs or failures of any kind.

It should be just like the first time the user tries to couple the app with his Facebook account: The standard "Grant access" page should be presented, because after all, the user tries to use something with Facebook, so that must mean he changed his mind, and wants to access Facebook even though he revoked access earlier on, and thus we should help him proceed.

uid: 73434 topic_id: 34416 reply_id: 141269


[TOPIC: post.html]
#63

haakon

[GLOBAL: userInfoPane.html]
haakon
  • Contributor

  • 188 posts
  • Enterprise

I implemented this myself in our nativefacebook enterprise plugin that contains a lot of missing Corona=>Facebook implementations. Works like a charm.
uid: 21746 topic_id: 34416 reply_id: 141270


[TOPIC: post.html]
#64

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

Hi, Tom, where are we with this? Do you think the HTTP Error 400 issue would be fully addressed anytime soon, or do you recommend I seriously consider reverting back to daily build 990? Not so far in the distant future (meaning definitely this month, and perhaps within the next couple of weeks), I'd like to finalize and submit my app for release.

If I can't expect this error to be fixed (or Corona side to come to some sort of resolution) sometime this week, I would need to revert back to 990 and test the app thoroughly to ensure nothing is breaking as I finalize the app. So please please please let me know the status of things.

Thanks,
Naomi

P.S. If you need more information as to where and how things break, please give me a shout. I'm more than happy to help getting this issue resolved.
uid: 67217 topic_id: 34416 reply_id: 141593


[TOPIC: post.html]
#65

cebodine

[GLOBAL: userInfoPane.html]
cebodine
  • Observer

  • 12 posts
  • Corona SDK

This is very frustrating! This bug (20096) was filed on January 9th and reported as soon as build 993 came out which implemented the Facebook 3.1 API.

We have received no fix for this or a date for when it might be fixed. We have received no workaround or working sample code.

This is a showstopper for us. We have a game pretty much ready to go except we can't get around this bug.

I don't believe this is a Facebook bug. I believe it's a Corona bug.

Please, Corona, assign somebody to this that can fix it.

Thank you,
Christopher Bodine
President, CloverLeaf Mobile Apps
http://www.cloverleafmobile.com
uid: 120928 topic_id: 34416 reply_id: 142001


[TOPIC: post.html]
#66

haakon

[GLOBAL: userInfoPane.html]
haakon
  • Contributor

  • 188 posts
  • Enterprise

Looks like this bug will be just as badly handled as the Android Push Notification feature was "back then".

I suggest that you rely on facebook.showDialog() for everything related to posting stuff. Getting a user's friends or extra user info is not requiring any permissions. If you need extra user info in /me, you can set that up on developers.facebook.com in your app.

The main things you'll be missing is the ability to post photos, post on behalf of the user on his/hers friends wall (it's already deprecated by Facebook, so that possiblity is about to go away). And if you have a server that posts achievements, scores etc on behalf of the user, that wont work without the publish_actions permission. The final part is what we miss the most => we've seen a dramatic change (negative) in user activity and reach after we lost that possibility.

If you are an Enterprise user you can implement the native share dialog to fix the photo posting issue.

I'll be writing a brand new facebook integration for Corona next week to get the publish permissions working again, since it's an important part of our marketing strategy. We can concider selling that plugin to other (frustrated) devs in the need of a working facebook integration. But you'll need Enterprise to use it.
uid: 21746 topic_id: 34416 reply_id: 142005


[TOPIC: post.html]
#67

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

I agree with Christopher @cebodine. This bug is a show stopper for me too. It really destroys Facebook aspect of the app. At this point, I'm sure it's Corona bug (not Facebook SDK bug, especially since haakon was able to fixed it with his version of FB SDK integration.)

I could use 990 as a stop gap measure -- perhaps get Apple to approve the app ahead of time and then do a quick update before releasing the app, but it really is going to be a very short term solution, especially since there are a whole host of other bugs that's been fixed since 990. I definitely need to use latest build for the final release that includes additional monetization features (such as iAds, RevMob, Chartboost, if ever it becomes available, etc.) Besides, I think using latest build is absolutely necessary for the Android version (again due to number of bug fixes that went in since 990.)

So, I'd very much like to know where we are at with this bug. Please?

Naomi
uid: 67217 topic_id: 34416 reply_id: 142007


[TOPIC: post.html]
#68

haakon

[GLOBAL: userInfoPane.html]
haakon
  • Contributor

  • 188 posts
  • Enterprise

@Naomi - Tom asked you to continue the discussion per e-mail. What happened with that? Was it just an attempt to silence this thread and hope that the community stopped asking for a fix? That's funny :)
uid: 21746 topic_id: 34416 reply_id: 142008


[TOPIC: post.html]
#69

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

@haakon, I sent him a few emails detailing my finding but I have not heard back from him. Maybe my email wasn't helpful? Because I thought I found the fix, and then it turned out it was a false alarm? I dunno.

BTW, the publish_actions permission is required for FB Score API too. Even though I use showDialog for posting anything on friend's wall, I still need publish_actions permission to post user's high score and retrieve friends' high scores. There's no way around it (short of begging users to restart the app as soon as they sign in to FB -- which is not an option at alll, honestly.)

Naomi
uid: 67217 topic_id: 34416 reply_id: 142010


[TOPIC: post.html]
#70

haakon

[GLOBAL: userInfoPane.html]
haakon
  • Contributor

  • 188 posts
  • Enterprise

I sat down to crack this thing, and have made a completely new implementation of facebooking for Corona. No need to own enterprise or anything, just copy this and use it instead of your old lua code.

I did not bother to change any of the code, so this is how we're using it. You need to clean it up and make adjustments for yourself.

We're giving NO SUPPORT for this piece of code! :)

With this Facebook implementation, you'll get the publish_actions permission from the user and will be able to post photos, scores, achievements etc. No more facebook sdk error #5.

So why does this work? By checking the access_token validity with facebooks open graph server, we're able to know if the access token is ok to use or not. If it is ok, then we can skip the login phase completely. Second, if the token is _not_ valid, we can clean up our facebook variables, logout the user (logout is not a global function in terms of Corona Facebooking, but app-sandboxed), and pop up the auth dialog.

How to use?

FaceSingleSignon(your_listener)

local obj = {
	message = "Message",
	source = { baseDir=system.TemporaryDirectory, filename="image.png", type="image" }
}
FacePublishPhoto(obj)

local facebook = require("facebook")
local appId  = "YOUR APP ID"
local fbListener
local fbCommand
local fbData
local fbCallback
local fbId

local LOGOUT = 0
local POST_MSG = 1
local POST_PHOTO = 2
local GET_FRIENDS = 3
local INVITE_REQUEST = 4
local SINGLE_SIGNON = 5
local FEED_GAME = 6

local function printTable( t, label, level )
	if label then print( label ) end
	level = level or 1
	if type(t) ~= "table" then
		t = json.decode(t)
	end
	if t then
		for k,v in pairs( t ) do
			local prefix = ""
			for i=1,level do
				prefix = prefix .. "\t"
			end

			print( prefix .. "[" .. tostring(k) .. "] = " .. tostring(v) )
			if type( v ) == "table" then
				print( prefix .. "{" )
				printTable( v, nil, level + 1 )
				print( prefix .. "}" )
			end
		end
	end
end

if simulator then
	facebook.login = function()
		native.setActivityIndicator(false)
		ui.newNotification("Facebook not available in simulator...", "error")
	end
else
	local old_login = facebook.login
	
	facebook.login = function(appId, params)
		if not _G.access_token then
			print("Got no access token")
			old_login(appId, fbListener, params)
		else
			network.request("https://graph.facebook.com/me?access_token=" .. _G.access_token, "GET", function(event)
				printTable(event, "facebook.login")
				if not event.isError then
					local data = event.response or "{}"
					data = json.decode(data)
					
					if data and data.error and data.error.type == "OAuthException" then
						print("OAuthException")
						_G.access_token = nil
						facebook.logout()
						old_login(appId, fbListener, {"publish_actions"})
						return false
					else
						-- Everything ok! We'll completely skip the login phase by hacking Coronas native implementation
						fbListener({type = "session"})
					end
				else
					-- Something unexpected happened, go ahead with a regular login
					print("Face, unexpected error")
					old_login(appId, fbListener, params)
				end
			end)
		end
	end
end

fbListener = function(event)
    if ("session" == event.type) then
		
		if event.phase == "logout" then
			return false
		end
		
		-- Save Access Token
		if event.token then
			_G.access_token = event.token
		end
		
		if fbCommand == FEED_GAME then
			facebook.showDialog("feed", fbData)
		end
		
		if fbCommand == POST_MSG then
			facebook.showDialog("feed", fbData)
		end
		
		if fbCommand == POST_PHOTO then
			facebook.request("me/photos", "POST", fbData)
		end
				
		if fbCommand == GET_FRIENDS then
			facebook.request("me/friends", "GET", {fields = "id, name, installed"})
		end
		
		if fbCommand == INVITE_REQUEST then
			facebook.showDialog("apprequests", fbData)
		end
		
		if fbCommand == SINGLE_SIGNON then
			facebook.request("me", "GET", {fields="id,username,name"})
		end

-----------------------------------------------------------------------------------------

    elseif "request" == event.type then
		native.setActivityIndicator(false)

		if not event.isError then
			
			local response = json.decode(event.response)
			if response then					
				if fbCommand == POST_MSG then
					ui.newNotification(t("notification.facebook_message_posted"))
			
				elseif fbCommand == POST_PHOTO then
					ui.newNotification(t("notification.facebook_message_posted"))
				
		        elseif fbCommand == GET_FRIENDS then
					fbCallback(response)
				
				elseif fbCommand == SINGLE_SIGNON then
					fbCallback(response)
					
				end
			else
				ui.newNotification(t("notification.facebook_request_failed"), "error")
			end
        else
        	-- Error
			facebook.logout()
			ui.newNotification(t("notification.facebook_request_failed"), "error")
			fbCallback = nil
			fbData = nil
			fbCommand = nil
		end
	elseif "dialog" == event.type then
		native.setActivityIndicator(false)
		
		if event.didComplete == true then
			if fbCommand == FEED_GAME or fbCommand ==  POST_MSG then
				if string.find(event.response or "", "fbconnect://success?post_id=", 1, true) then
					ui.newNotification(t("notification.facebook_message_posted"))
				end
				
			elseif fbCommand == INVITE_REQUEST then
				local status = "success"
				if ios and not string.find(event.response or "", "request=", 1, true) then
					status = "error"
				end
				fbCallback(status)
			end
		end

		fbCallback = nil
		fbData = nil
		fbCommand = nil
		
    end
end

-- Publish a feed
function FacePublishFeedGame(data)
	fbCommand = FEED_GAME
	fbData = data
	facebook.login(appId)
end

function FacePublishFeed(data)
	fbCommand = POST_MSG
	fbData = data
	facebook.login(appId)
end

function FacePublishPhoto(data)
	fbCommand = POST_PHOTO
	fbData = data
	facebook.login(appId)
end

function FaceInviteFriends(data, cb)
	fbCommand = INVITE_REQUEST
	fbData = data
	fbCallback = cb
	facebook.login(appId)
end

function FaceGetFriends(cb)
	fbCommand = GET_FRIENDS
	fbCallback = cb
	facebook.login(appId)
end

function FaceSingleSignon(cb)
	fbCommand = SINGLE_SIGNON
	fbCallback = cb
	facebook.login(appId, {"publish_actions"})
end

function FaceLogout()
	_G.access_token = nil
	facebook.logout()
end

end

Enjoy a working Facebook implementation again!
uid: 21746 topic_id: 34416 reply_id: 142075


[TOPIC: post.html]
#71

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

Hey, Haakon, thank you for posting this. I'll give it a shot and see if it works for what I need to do with mine. I appreciate you sharing your code.

Thanks again.

Naomi

Edit: Haakon, unfortunately, your workaround doesn't work for my FB login/request flow... The initial FB login through the series of request (connecting to FB, retrieving me, posting score, retrieving app/score) works, but all subsequent requests do not work (not only retrieving me/friends or posting with showDialog but any new round of posting high score and retrieving app/score), which basically kills FB feature. In my case, with this workaround, restarting the app doesn't fix the FB issue the way it did before. I'm still better off reverting back to how it was before. It works perfectly fine with 990, and with 1025, killing the app once fixes the issue (although, it really isn't an option for Apple submission candidate.) That said, I'm glad it works for you. It could be that I didn't implement your workaround exactly how it should be done, but then, my app is different from yours, and it goes through different steps. Please note, FB issue only occurs on specific FB login/request flow, i.e., CASE 5 and CASE 7. If the user logs in with permission in a separate scene from where subsequent FB login/requests take place, my app does not trigger any FB error.
uid: 67217 topic_id: 34416 reply_id: 142102


[TOPIC: post.html]
#72

haakon

[GLOBAL: userInfoPane.html]
haakon
  • Contributor

  • 188 posts
  • Enterprise

@Naomi, the things you say about scenes really don't make any sense to me. The class above should be referenced in your main.lua file, and you should keep a global variable for the access_token.

main.lua
face = require("Face")
access_token = nil

If you keep the code I posted as it is (but remove ui.newNotification or replace it with prints, showAlert or something else), and adds in your own shorthand functions for stuff like FacePostScore etc, using the same code style as I have done, it should work fine.

I'm quite sure you have done something to the code that makes it break, there's no reason it should break if you stick to the patterns in my code. Don't change facebook.login = function, for instance. That override is there by purpose.
uid: 21746 topic_id: 34416 reply_id: 142138


[TOPIC: post.html]
#73

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

@haakon, thank you for the note. I do use a variable for access_token that is not global but accessible from any scene that I need to retrieve the token for (and I override and re-save a new token if/when FB listener returns valid event.token just to make sure.) I also require facebook as local function in each module where facebook is called for. Perhaps making it global is necessary, and maybe that's the whole problem I encountered with your workaround...

But then, it still doesn't make much sense, because the entire workaround I implemented takes place inside a single module/scene, and I call facebok.login with permission only once (and only if/when there's no access_token.)

Hmmm... as I was writing, I generated a new built with the pre-workaround code. Very odd. Native alert message pops up upon initial login -- which is rather very strange. I attributed this native alert to your workaround, but perhaps its something else. I built my app and tested CASE 5 & CASE 7 using daily build 990 and 1013 previously. This morning, however, I downloaded daily build 1025 (and deleted 1013) before implementing your workaround. And then I get this native alert message, and other issues. So, I reverted back to my pre-workaround code and built my app again... and it still brings up this native.alert... I thought it was your workaround that caused it to show up, but maybe it's the latest daily build that does it, and whatever else is odd about it may have something to do with it too? I don't know. I'll try CASE 7 with 990 and 1013 (using my pre-workaround code.) And if it behaves the way I'm familiar with, I'll try your workaround and see if works with daily build 1013. How confusing...

Naomi
uid: 67217 topic_id: 34416 reply_id: 142145


[TOPIC: post.html]
#74

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

Okay, I get same native alert with both daily build 990 and 1013, plus errors that previously did not exist.

It turns out it has something to do with installing it on iOS6.1 device. The app built with iOS SDK 6.0 via daily build 990 spits out the very same errors when installed on a device with iOS6.1.

The app works only if I build it with daily build 990 and install it on a device with iOS 6.0 (or pre-iOS 6.0) At this point, I don't have an app with FB feature that runs without any error on iOS6.1 device. Yikes. This is a major setback. Back to code review -- and I really have to work on getting Haakon's workaround working with daily build 1025 -- otherwise, my app submission is not happening.

EDIT: The strange native alert was something to do with testing on a device that has already FB approved (via a version of an app built with iOS6.0 SDK). Instead of wiping the device, I simply deleted the app and then installed a new version of the app built with iOS6.1 SDK -- this triggered this strangeness and inexplicable errors that I could not work around. Once I wiped the device (by resetting all content) and installed the new version of the app built with iOS6.1 SDK, the odd alerts and error messages went away -- meaning, once I clean slated the devices (both iOS6.0 device and iOS6.1 device), the app built with 1025 returned back to the behavior I observed in CASE 5 & CASE 7, and yes, restarting the app does fix the Facebook issue and normalize the app. (The strange errors would've been worrisome if I had an already released app built with pre-iOS6.1SDK that desperately needed the update/fix with the new Facebook SDK.)

The next step -- if I got the energy and can put aside some time for it, I might just go ahead and create a test project that only include main.lua with code that demonstrates CASE 7 (and perhaps I'll send it in to Corona in case that helps identify where our trouble lies.) And then, I may proceed to convert the test project to include Haakon's work around. If the work around works in the reworked version of the test project, then I have a reason to further rework my app -- and perhaps send the reworked test project to Corona too so that they may finally get around to fixing the issue...

EDIT 2: I filed Case 20794 with the test project that demonstrates CASE 7 (tested with daily build 1025 on both iOS 6.0.1 and iOS 6.1 devices). The test project is stripped down to the core FB mechanics that fails. In the process, I found that if I install the test app on cleanly wiped device, it normalizes after I restart the app upon encountering the HTTP 400 error and other FB failures. Once it normalizes, the FB feature works flawlessly. However, if I delete the app from the device, and reinstall the very same app, the FB feature is completely destroyed, and the app becomes utterly dysfunctional.
uid: 67217 topic_id: 34416 reply_id: 142154


[TOPIC: post.html]
#75

schizoid2k

[GLOBAL: userInfoPane.html]
schizoid2k
  • Contributor

  • 562 posts
  • Corona SDK

I hope you don't mind me jumping into this thread...

I've been reading this thread over and over with a lot of interest (thanks Naomi and haakon), but I am unsure what I need to do to make my app play nice with Facebook.

I want to add a Like button, wall posting, and maybe a way to grab friends for a challenge mode in my app (that depends on what Game Minion will deliver I guess), and I am unsure what build to use, what params to pass to FB, and what return and/or error values to expect.

Even in simpler times, facebook integration was something I wasn't sure about successfully implementing. With my new app, I need to add more fb features, and now I am just completely confused.

Will there be an improvement in the builds to handle this (soon)? If not, what's the solution? I also tried the GGFacebook library with limited success... perhaps whatever happened also affected this library?

FB integration is almost a must now, so any help sorting this out woudl be great.
uid: 114363 topic_id: 34416 reply_id: 142285



[topic_controls]
Page 3 of 6 1 2 3 4 5 »
 
[/topic_controls]