When removing Flash objects in Internet Explorer, THEY STILL STAY ACTIVE! - 2 ways to handle it.
This is an old known problem (possibly dating back to several years ago), that is present on the Flash Player version for Internet Explorer:
When you embed a Flash Object in an HTML, and view it using IE:
if you remove the object (either by using your own JS in the html page, or sometimes even when a user closes the tab of the page (but not the browser)) - the flash object actually still stays open! : If the flash application has opened any connections to a remote flash server, or to a local connection - the connections will remain open and connected. If the flash app was streaming a video - the video will still keep streaming (you won’t see it, since the visual does get removed - but you will still be able to keep hearing its sound).
If another flash will be opened - it will be opened in addition to the previous non-closed flash, and both will consume resources and memory, same when a third one is opened, and a forth, and so on… - leading to a progressing strangle of the user’s system resources, causing each new opened Flash to be more slow and lazy (not to mention wasting unnecessary bandwidth on the server) … until the user closes Internet Explorer entirely.
Here are two ways to deal with this harsh and ugly bug:
1. Handling from the “outside”
Javascript in Internet Explorer supports an event called
onbeforeunload, this event triggers just before a window is unloaded from view (works for iframes as well). You can handle this event in your JS code, and using the
AS3 ExternalInterface API, call an ActionScript function inside the Flash, that will handle all the proper closing of the connections.
If you use swfobject, then the script in swfobject can handle a proper cleanup for you. Each time you add the swfobject.js script to your page - it will automatically handle the unload event, and it can also identify if the browser is IE and does extra cleanup that will in-fact make sure that the object will be removed in a correct way that makes the connections close and so on.
You can also use swfobject.removeSWF method to call for a proper cleanup of the flash object.
However, there is a still a scenario in which this is not enough to make sure the problem is eliminated, like situations such as this:

In this situation - there’s an iframe with a flash object embedded in it, and upon clicking on any of the “room” links on the side - the iframe will be loaded with a different page and a different flash object. Let’s say the flash is embedded using swfobject.
There is a situation where a user can click fast enough between the rooms, in a way that the flash object does not yet get fully loaded and embedded before the cleanup routine of swfobject is called (or before you call removeSWF yourself) (this was actually a common scenario in a video-chat website of ours); The cleanup routine will not be able to identify the existence of the flash object, as it was not been fully added to the page yet, and it will “skip” and “miss” it. After that, the flash will load, but the unload routine was already finished - and thus the flash will stay loaded even though the user changed rooms.
To address this problem - you need to make sure the embedding of the flash object is complete, before allowing any option for it to be unloaded. To do that you can use the callback option of the embedSWF function of swfobject. Everytime the iframe with the flash loads, you should block the ability to change rooms for the users (like placing a semi-transparent div over the rooms links) - and once the embedSWF finishes and calls your callback you can then enable room-switching again.
2. Handling from the “inside”
There are some situations, though, when you will not have any control over the parent page where the swf flash is embedded, and won’t have any access to the Javascript in that page. One example for that is - if your flash is embedded in Facebook. Then you have no control of if and how it was embedded or if and how it was removed, and on IE when running embedded Flash in Facebook - this problem WILL show its ugly face again.
To address this, you need to somehow know if the flash is still in a “visible” state or not, from within the Actionscript code inside the flash itself.
To do that, you can use the ExternalInterface.objectID property. This property should return the string of the id attribute of the Flash object in the parent page. If the object is gone then this string should be empty or undefined - and that will mean that the flash object was removed/became nonvisible.
And so, you can create a timer in your Flash code, running every so and so seconds, that on each run will check if ExternalInterface.objectID contains a value, and if it is empty - you can then initiate your cleanup code from with the Flash.
If you know what the ID string should be - then you can check for that string,
in the situation of embedding in Facebook, you will not have the option to know the expected string of the ID attribute (their code assigns a different string each time) - but you can simply test if it has any value or not.
February 14, 2012 at 1:04am
1 note
“Connect with Facebook” workflow from Flash/AS3 using only the Facebook PHP API
This tutorial will show you how to let users connect with their Facebook account (i.e. - allow your application to collect their Facebook details such as their name, ID, picture, profile-link and so on…) from within a Flash application, without using any external ActionScript libraries or classes.
Setting up the server-side PHP
Install and setup the Facebook PHP SDK
To gain access to a Facebook user logged-in account, you need to setup a
Facebook application.
Each user will need to authorize your app (one time only) to allow your app access to his Facebook details.
To setup a new Facebook app, use this interface in the Facebook Developers website.
Once your app is set up, you will have an App ID, and an App Secret both assigned for it automatically by the Facebook app configuration site.
Save those for later. You will use those when using the PHP SDK.
The PHP SDK for Facebook can be downloaded from here.
To access its functions you need to instantiate a Facebook object, for example:
<?php
require_once('facebook.php');
$facebook = new Facebook(array(
'appId' => 'YOUR_APP_ID',
'secret' => 'YOUR_APP_SECRET'
));
?>
and then you can use its functions, for example:
$fbID = $facebook->getUser();
which tries to retrieve the Facebook ID of the currently logged-in user.
These steps are also described in the
PHP SDK Overview page at Facebook.
We are going to create a PHP page that accomplish the following:
If a user is logged-in with Facebook and is connected to your app, return his Facebook ID.
If not, redirect him through the login and authorization process, then return his Facebook details.
We’ll call it getfbuser.php:
<?php
require_once 'facebook.php';
$facebook = new Facebook(array(
'appId' => APP_ID,
'secret' => APP_SECRET,
));
$fbUid = $facebook->getUser();
// We also require a 'doLogin' query parameter to initiate the login redirection.
if (!$fbUid && isset($_GET['doLogin'])) {
$fb_LoginURL = $facebook->getLoginUrl(array(
'scope'=>'[..]', // <- You can specify here any additional "extended permissions"
your app requires. For example the 'publish_stream' permission will allow
your app to publish on the user's wall...
'redirect_uri'=>'postfblogin.php' // This is where the user will be redirected to
after the login to Facebook is finished. We will create this post-login script later.
));
// Redirect the user to the login/authentication process:
header('Location: '.$fb_LoginURL);
exit();
}
else
{
//If we got his ID - return it.
echo $fbUid;
exit();
}
?>
Writing the ActionScript in Flash
Have a symbol in your library of a button containing a bitmap of a “Facebook Connect” button, for example like this one:

Make sure the “
Export for ActionScript” in the Linkage field is set with a class name. We’ll call ours “
FBCONNECT”.
We will create a Flash app that displays the user profile picture along with his name that is also a link to his Facebook profile.
First, let’s create a ‘utility function’ that can initiate an asynchronous HTTP POST to a remote URL:
function doHttpPOST (posturl:String,oncompleteFunc:Function) {
var req:URLRequest = new URLRequest(posturl);
req.method = URLRequestMethod.POST;
var reqLoader:URLLoader = new URLLoader();
reqLoader.addEventListener(Event.COMPLETE,oncompleteFunc);
reqLoader.load(req);
}
The return value of the POST will be inside the Event parameter of the oncompleteFunc, in event.target.data
Upon startup , we will try to get the user’s Facebook ID by posting to the PHP we created in the first step.
If the user is logged-in to Facebook and is connected with your app, the PHP should return his user ID.
// This is where we're gonna store the user's FB details once we have them:
var facebookUser:Object = new Object();
doHttpPOST("getfbuser.php",function(e:Event)
{
// The getUser() function of the PHP SDK returns 0 if it can't get
an ID - that means the user is not connected, and we show a
"Facebook connect" button:
if (uint(e.target.data) == 0) {
var fbConnectBtn = new FBCONNECT();
fbConnectBtn.addEventListener(MouseEvent.CLICK,
function(e:MouseEvent) { doFBConnect(); });
addChild(fbConnectBtn);
}
// If the user is already connected and we have his ID, we can go ahead
and use the 'Graph API' to display his information:
else if (uint(e.target.data) > 0) {
facebookUser['id'] = String(e.target.data);
getFBInfo();
}
});
The
getFBInfo function will retrieve the user’s basic details via the Graph API, using the ID we got. If you want to access more extended nonbasic details about the user, you will need to obtain an “
access token”, this process is also explained later on. For now, let’s just get those basic details we need:
function getFBInfo() {
doHttpPOST ("https://graph.facebook.com/"+facebookUser['id'],function(e:Event) {
onGetFB(e.target.data);
});
}
function onGetFB(fbUser:String) {
// The Graph API returns the user details as a JSON string, you can use your
favorite external ActionScript JSON deserializer, or simply do it "by hand",
like in this example:
var findex = fbUser.indexOf('"name":"')+8;
facebookUser['name'] = fbUser.substring(findex,fbUser.indexOf('"',findex));
findex = fbUser.indexOf('"link":"')+8;
facebookUser['link'] = fbUser.substring(findex,fbUser.indexOf('"',findex)).replace(/\\/g,'');
//Get the profile picture:
facebookUser.picture = new Bitmap(new BitmapData(50,50,false,0x000000));
var picLoader:Loader = new Loader();
picLoader.contentLoaderInfo.addEventListener(Event.INIT,function(e:Event) {
facebookUser.picture.bitmapData.draw(picLoader);
facebookUser.picture.smoothing = true;
// When we got what we needed - show the user.
showFBUser();
});
picLoader.load(new URLRequest("https://graph.facebook.com/"+facebookUser['id']+"/picture"));
}
The
showFBUser function will use the obtained information and display it:
function showFBUser() {
var userSpr:Sprite = new Sprite();
var userNameText:TextField = new TextField();
userNameText.defaultTextFormat = new TextFormat
('Arial',18,0x0000cf,true,false);
userNameText.width = 200;
userNameText.x = 54; userNameText.y = 2;
userNameText.htmlText = "<a href='"+facebookUser['link']+"'>"
+facebookUser['name']+"</a>";
userSpr.addChild(facebookUser.picture);
userSpr.addChild(userNameText);
addChild (userSpr);
}
Here is an example for a sample result display:

The name will be a clickable hyperlink that opens a new browser-window with the user’s Facebook profile in it.
Handling a new user login/connection
As you recall when we first do a POST to the php to get the user’s id, one of the options is that the user is not connected to your app and/or not logged-in to Facebook. In that case, we displayed a “Connect with Facebook” button. We will deal with that button’s functionality next (of-course you could also simply trigger that functionality automatically instead of putting the button, but there will be a difference - see below after the code block):
function doFBConnect() {
ExternalInterface.call("FBWin = window.open",'http://url/getfbuser.php?doLogin',
'_blank',"width=1016,height=624,location=no,menubar=no");
}
What this will do is run a little bit of
Javascript code that will open a new window where the user can do the login (this is handled by the php code we wrote earlier, that uses the
getLoginUrl function from the Facebook PHP SDK).
We also save a reference for the window (‘
FBWin’) so we could later close it automatically once we no longer need it.
[Note about not using a button and instead just opening the window: most browsers have a “pop-up blocker” that only allows code that opens a new window to run if it was initiated by a user (like clicking on a button). I’m pretty sure that if you won’t use a button - the new popup window will be blocked and the user will have to allow it first…]
If the user is not logged-in to Facebook - he will be presented with Facebook’s login screen on the pop-up window.
If the user never used your APP before, he will be presented with Facebook’s “app authorization” screen.
In any case, after that, there should be a redirection to the url we specified in the ‘redirect_uri’ parameter we specified back in the PHP.
We wrote the redirect to be to a file called ‘postfblogin.php’.
Handling post-login / User Authorization
The redirection occurs with added querystring parameters that Facebook adds to the url.
If there was any error during the login-process the parameter ‘
error’ will be added.
If the login was ok - a ‘
code’ parameter is added to the url.
The next step is to use this “code” to obtain an “access token”. This access token can then be used to get information about the currently logged in user, by using the Graph API “/me” connection.
(An access token can also be used to query other non-public parts of the Graph API).
To obtain an access token you use the URL:
“https://graph.facebook.com/oauth/access_token”
This URL needs to accept four parameters:
- code: The ‘code’ we got in the ‘code’ parameter in this stage.
- client_id: Your FB app ID.
- client_secret: Your FB app Secret.
- redirect_uri: *must* be the same as the previous “redirect_uri” parameter that got us here.
[For more information relating to this, you can also read the document on “Authentication” at Facebook.]
So, the PHP code for the ‘
postfblogin.php’:
// Handle errors:
if (isset($_GET['error'])) {echo 'ERROR'; die(); }
// If ok:
if (isset($_GET['code'])) {
$thecode = $_GET['code'];
$redirectURI = "postfblogin.php";
$getaccessURL =
'https://graph.facebook.com/oauth/access_token?'.
'client_id='FB_APP_ID&' .
'client_secret=''FB_APP_SECRET&' .
'code=' . $thecode . '&redirect_uri=' . $redirectURI;
// If it works you should get back an access token,
and an "expiry date" parameter.
$accessResponse = @file_get_contents($getaccessURL);
$accessData = null;
// Seperate the token from the expiry parameter:
parse_str($accessResponse,$accessData);
// Now, using the access token, we can access the Graph API '/me':
$userDetails = json_decode(file_get_contents(
"https://graph.facebook.com/me?access_token=" .
$accessData['access_token']));
}
Callbacking the ActionScript / Back to the Flash
We now have the information we wanted about the Facebook user.
We need to send it back to our Flash app somehow, and arise a callback function.
To do that, we can use the
LocalConnection ActionScript class.
Back in our Flash program, we add:
var localCon:LocalConnection = new LocalConnection();
// You can give any string as the "connect" parameter,
but it must be identical in the "other side".
We're gonna write the "other side" after this part...
localCon.connect("facebookConnect");
localCon.client = this;
// Define a callback to accept the collected information:
function onFBConnectBack(fbParams:Object) {
// Close the pop-up window we opened earlier for the login,
using Javascript and the window reference we saved when we opened it.
ExternalInterface.call("FBWin.close");
// The fbParams parameter should be an object with everything we need,
so just assign it to our other object:
facebookUser = fbParams;
//Get Profile picture from the Graph API:
facebookUser.picture = new Bitmap(new BitmapData(50,50,false,0x000000));
var picLoader:Loader = new Loader();
picLoader.contentLoaderInfo.addEventListener(Event.INIT,function(e:Event) {
facebookUser.picture.bitmapData.draw(PicLoader);
facebookUser.picture.smoothing = true;
});
picLoader.load(new URLRequest("https://graph.facebook.com/"
+facebookUser['id']+"/picture"));
// The 'Facebook connect' button is no longer required:
removeChild(fbConnectBtn);
// The object is filled with the information. Display it:
showFBUser();
}
Trigger the callback from the PHP
We now need to create
an additional SWF file, containing very short code to send back the information to our original Flash object and trigger the callback function. Let’s call it ‘
fbconnect.swf’.
The code for this flash:
// stage.loaderInfo.parameters is an object that automatically gets
assigned with all the variables in the flashVars parameters of a
flash object. We're going to use that for our advantage:
var fbParams:Object =
stage.loaderInfo.parameters;
var localCon:LocalConnection = new LocalConnection();
// for the 'send' method - the first parameter is the "connection string",
the second is the name of a function defined on the other side,
and the third is any additional parameters for that function
localCon.send("facebookConnect", "onFBConnectBack",fbParams);
What’s left is to embed the sending Flash object into the post-login PHP.
Extend the if-block, and add:
// At this point $userDetails is an array with keys->values of
information about the user. We need to turn it into a "querystring"
format, as we're gonna use 'flashVars' to pass it.
Let's just put the things we need:
$userDetailsVarStr = "id=" . $userDetails->id .'&' .
"name=" . $userDetails->name . '&' .
"link=" . $userDetails->link;
// Now simply embed the 'fbconnect' flash into the page, and give it
the relevant flashVars:
echo '<embed src="fbconnect.swf" width="0" height="0" hidden="true"
flashVars="'.$userDetailsVarStr.'" />';
…and this will trigger the onFBConnectBack function back in the original Flash, giving it the information we need (and it’ll also take care of closing the popup window…)
and that’s it!