Authorizing Facebook Applications in Android

Hold on, this is going to be fast and smooth! I am playing with an Android Emluator for a few days now. One of the challenges was to mount FacebookOAuthGraph lib into Android. It turned out to be 1 hour task. Thanks to Flash-Core article and sHTiF and StageWebView. Long live AIR for Android!
Follow the article for codes:
You do not need a callback.html file, as in previous AIR example, you can use non existing redirect_uri targeting correct domain + a simple extending of FacebookOAuthGraph:
package
{
import flash.display.Stage;
import flash.events.LocationChangeEvent;
import flash.geom.Rectangle;
import flash.media.StageWebView;
import onboard.Controller;
public class FacebookAndroid extends FacebookOAuthGraph
{
public var loader:StageWebView;
public var stage:Stage; // this is the air application Stage
public function FacebookAndroid()
{
super();
}
override public function connect():void
{
var bounds:Rectangle = new Rectangle(0,0,480,480);
loader = new StageWebView();
loader.addEventListener(LocationChangeEvent.LOCATION_CHANGING, onLocationChanging);
loader.addEventListener(LocationChangeEvent.LOCATION_CHANGE, onLocationChange);
loader.stage = stage;
loader.viewPort = bounds;
loader.loadURL(authorizationURL);
}
private function onLocationChanging(event:LocationChangeEvent):void
{
event.preventDefault();
loader.loadURL(event.location);
}
private function onLocationChange(event:LocationChangeEvent):void
{
var hash:String = locationExtractHash(loader.location);
var error:String = locationExtractError(loader.location);
if(hash)
confirmConnection(hash);
if(hash || error)
destroyLoader();
}
protected function locationExtractHash(url:String):String
{
var index:int = url.indexOf("#");
if(index <= -1)
return null;
var hash:String = url.substr(index + 1);
return hashToToken(hash) ? hash : null;
}
protected function locationExtractError(url:String):String
{
var index:int = url.indexOf("?");
if(index <= -1)
return null;
var query:String = url.substr(index + 1);
var variables:URLVariables = new URLVariables(query);
return variables.hasOwnProperty("error") ? variables.error : null;
}
private function destroyLoader():void
{
loader.removeEventListener(LocationChangeEvent.LOCATION_CHANGING, onLocationChanging);
loader.removeEventListener(LocationChangeEvent.LOCATION_CHANGE, onLocationChange);
loader.dispose();
loader = null;
}
}
}
How does this works? You do not need any callback.html, just generate some redirect_uri that correctly targets your domain, it can be anything, even 404.html, or asdf-foo-bar.html file that does not exist. Once the Facebook, redirects you back to the redirect_uri, the url contains access_token within url hash
http://domain/whatever-or-404.html#access_token=123
… now, if it does, it is parsed by locationExtractHash(), if it does not, the url contains error (user clicked Cancel button), the url contains error:
http://domain/whatever-or-404.html?error_reason=user_denied&error=access_denied&error_description=The+user+denied+your+request.
In case of error locationExtractError() parses and error. In both cases (error or access_token), the HTMLLoader window is closed and token is handled via confirmConnection(). Yeah, this way you can authorize !ANY! existing facebook application for your AIR app.
sHTiF also did a good job commenting all the functions, follow his the article to understand LocationChangeEvent listeners.